функции (начать, закрепить, отменить действие). Если требуется закрепить или отменить выполненные изменения, то необходимо хранить состояние объекта на заданный момент – начало транзакции, и в момент принятия решения фиксации транзакции или уничтожать предыдущее состояние (закрепление транзакции), или возвращаться к предыдущему состоянию (отмена транзакции). Механизм транзакций можно рассмотреть на примере следующей программы.
//Пример №2. Использование механизма транзакции #include <locale.h>
#include <iostream> using namespace std;
//класс, над объектами которого выполняются транзакции template <class T1>
class Account { T1 number;
public:
Account() : number(0) {}
void set(int number) { this->number = number; } // инициализация объекта
T1 get() { return number; } // возвращается значение объекта
};
//класс поддержки транзакций
template <class T2> class Transaction {
T2* currentState; // текущее значение объекта класса
T2* prevState; // предыдущее значение объекта класса public:
Transaction() :prevState(NULL), currentState(new T2) {} // конструктор
Transaction(const Transaction & obj) : currentState(new T2(*(obj.currentState))), prevState(NULL) {}
~Transaction() { delete currentState; delete prevState; } // деструктор
Transaction& operator=(const Transaction & obj); // перегрузка операции присваивания
void show(int);//отображение состояний (предыдущего и текущего) объекта
int BeginTransactions(int); // метод начала транзакции void commit(); // метод подтветждения (коммита) транзакции void DeleteTransactions(); //метод отката транзакции
T2* operator->(); // перегрузка операции ->
};
//перегрузка оператора = template <class T2>
Transaction<T2>& Transaction<T2>::operator=(const Transaction<T2> & obj)
{
if (this != &obj) // проверка на случай obj=obj
{
delete currentState; // удаление текущего значения объекта currentState = new T2(*(obj.currentState)); // создание и
копирование
}
return *this;
}
//перегрузка оператора ->
template <class T2>
T2* Transaction<T2>::operator->()
{
return currentState;
}
//метод отображения состояния объекта template <class T2>
void Transaction<T2>::show(int account) { cout << "состояния объекта ";
if (!account) cout << "до начала транзакции " << endl; else cout << "после выполнения транзакции " << endl;
if (prevState) cout << "prevState = " << prevState->get() << endl;
//предыдущее состояние
else cout << "prevState = NULL" << endl;
cout << "currentState = " << currentState->get() << endl; // текущее состояние
}
template <class T2>
int Transaction<T2>::BeginTransactions(int number) {// метод начала транзакции
delete prevState; // удаление предыдущего значения prevState = currentState; // текущее становится предыдущим
currentState = new T2(*prevState); // создание нового значения текущего состояния
if (!currentState) return 0; // ошибка (необходимо отменить действие)
currentState->set(number); // изменение состояния объекта return 1; // успешное окончание транзакции
}
template <class T2>
void Transaction<T2>::commit() {// метод подтветждения (коммита)
транзакции
delete prevState; // удаление предыдущего значения prevState = NULL; // предыдущего состояния нет
}
template <class T2>
void Transaction<T2>::DeleteTransactions() {//метод отката транзакции if (prevState != NULL) {
delete currentState; // удаление текущего значения currentState = prevState; // предыдущее становится текущим prevState = NULL; // предыдущего состояния нет
}
}
int main() {
Transaction<Account<int>> firstTransaction; setlocale(LC_ALL, "Russian");
firstTransaction->set(5); // начальная инициализация объекта firstTransaction.show(0);
cout << "НАЧАЛЬНАЯ ИНИЦИАЛИЗАЦИЯ ПРОШЛА УСПЕШНО" << endl; cout << endl;
cout << "ПЕРВАЯ ТРАНЗАКЦИЯ НАЧАТА СО ЗНАЧЕНИЕМ 10" << endl;
if (firstTransaction.BeginTransactions(10)) // начало транзакции
(изменение объекта)
{
firstTransaction.show(1);
firstTransaction.commit(); // закрепление транзакции
}
cout << "ПЕРВАЯ ТРАНЗАКЦИЯ ПРОШЛА УСПЕШНО" << endl; cout << endl;
firstTransaction.DeleteTransactions(); // отмена транзакции при ошибке
cout << "ПЕРВАЯ ТРАНЗАКЦИЯ БЫЛА ОТМЕНЕНА" << endl; firstTransaction.show(0);
cout << endl;
cout << "ВТОРАЯ ТРАНЗАКЦИЯ НАЧАТА CO ЗНАЧЕНИЕМ 2" << endl;
if (firstTransaction.BeginTransactions(2)) { // начало транзакции
(изменение объекта) firstTransaction.show(1);
firstTransaction.commit(); // закрепление транзакции
}
cout << "ВТОРАЯ ТРАНЗАКЦИЯ ПРОШЛА УСПЕШНО" << endl; firstTransaction.show(0);
return 0;
}
Результаты работы программы:
ВОПРОСЫ И УПРАЖНЕНИЯ ДЛЯ ЗАКРЕПЛЕНИЯ МАТЕРИАЛА:
1.Каковы особенности и использования динамической памяти в С++?
2.С какой целью используются smart-указатели? Каковы особенности их использования? Что представляет собой smart-указатель?
3.Что такое утечка памяти в программировании?
4.Что такое висячая ссылка (висячий указатель)?
5.Какие виды интеллектуальных указателей предоставляет библиотека С++?
6.Что собой представляет идиома программирования RAII?
7.Что такое транзакция в программировании? В чем состоит механизм транзакций?
8.Какие основные операции используются при реализации механизма транзакций?
ПОРЯДОК ВЫПОЛНЕНИЯ РАБОТЫ:
1.Изучить краткие теоретические сведения.
2.Ознакомиться с материалами литературных источников и материалами лекций.
3.Ответить на контрольные вопросы.
4.Разработать алгоритм программы.
5.Написать, отладить и выполнить программу.
6.Написать электронный отчет по выполненной лабораторной работе.
ВАРИАНТЫ ИНДИВИДУАЛЬНЫХ ЗАДАНИЙ:
1.Разработать набор классов (минимум 5 классов) по теме издательство
печатной продукции. Использовать smart-указатели для созданий программы учета деятельности издательства. Имеется несколько объектов печатной продукции и некоторое количество сотрудников издательства, которые работают с издаваемой продукцией. Печатная продукция считается готовой к изданию, когда с ней не работает ни один сотрудник издательства. Разработанный набор классов должен иметь параметры типа. Все классы должны иметь методы получения и изменения своих полей. Реализовать механизм транзакций, который позволит сотрудникам откатывать изменения, внесенные в печатную продукцию.
2.Разработать набор классов (минимум 5 классов) по теме делопроизводство. Использовать smart-указатели для создания программы учета делопроизводства в учреждении образования. Имеется несколько объектов документации и некоторое количество сотрудников учреждения образования, которые работают с документацией. Документ считается сформированным, когда с ним не работает ни один сотрудник. Разработанный набор классов должен иметь параметры типа. Все классы должны иметь методы получения и изменения своих полей. Реализовать механизм транзакций, который позволит сотрудникам откатывать изменения, внесенные в документы.
3.Разработать набор классов (минимум 5 классов) по теме сотрудники ИТ-
организации. Использовать smart-указатели для создания программы учета сведений о сотрудниках и расчета для них заработной платы. Разработанный набор классов должен иметь параметры типа. Все классы должны иметь методы получения и изменения своих полей. Реализовать механизм транзакций, который позволит откатывать изменения, внесенные в сведения о сотрудниках ИТ-организации. Предусмотреть возможность автоматического «отката» к предыдущему состоянию данных о сотруднике, если текущее состояние является неудовлетворительным. Смоделировать данную ситуацию.
4.Разработать набор классов (минимум 5 классов) по теме использование текстового редактора пользователями с автоматическим сохранением данных в файл. Редактор должен поддерживать возможность отмены внесенных изменений (отменить ввод, Undo, Ctrl+Z) и восстановления отмененной информации (вернуть ввод, Ctrl+Y, Redo). Для хранения историй модификации файла использовать список (его рациональную организацию определить самостоятельно). Разработанный набор классов должен иметь параметры типа. Все классы должны иметь методы получения и изменения своих полей. Использовать smart-указатели для создания программы, которая определяет возможность самостоятельного закрытия файла (т.е. данные файла сохранены и с ним никто сейчас не работает).
5.Разработать набор классов (минимум 5 классов) по теме банковские операции. Использовать smart-указатели для создания программы учета проводимых банковский операций и подсчета количества различных видов (переводы денежных
средств, оформление договора поручительства, выдача справки и т.д.) банковских операций и сумм по ним. Реализовать механизм транзакций, который позволит откатывать изменения, если операция выполнена неверно (например, произведена попытка списать со счета больше, чем на нем имеется, неверно указаны данные в договоре). Программа должна обеспечивать вывод информации о проведении банковских операций только по запросу клиента. Разработанный набор классов должен иметь параметры типа. Все классы должны иметь методы получения и изменения своих полей.
6.Разработать набор классов (минимум 5 классов) по теме «Розничная продажа товаров и услуг». Использовать smart-указатели для создания программы учета продаваемых и закупаемых товаров. Реализовать механизм транзакций, который позволит откатывать изменения, если данные о товаре введены неверно (например, покупатель отказался оплачивать товар). Разработанный набор классов должен иметь параметры типа. Все классы должны иметь методы получения и изменения своих полей. Программа должна обеспечивать вывод информации об осуществленных покупках и итоговой сумме только по запросу клиента.
7.Разработать набор классов (минимум 5 классов) по теме «Тестирование знаний студентов», включающий обязательно следующие классы: «Тест» (название теста, тема теста, перечень вопросов, перечень полученных ответов), «Пользователь» (ФИО, факультет, номер группы), «Ответ» (дата выполнения теста, ФИО выполнившего тест). Использовать smart-указатели для создания программы учета полученных ответов на тесты. Реализовать механизм транзакций, который позволит откатывать изменения, внесенные в ответ. Все классы должны быть параметризированными и содержать функции получения и изменения всех полей. Программа должна обеспечивать вывод итоговой информации о выполнении тестов.