|
Стеки образов Для многоуровневой отмены вам может понадобиться стек предыдущих образов. Один из вариантов реализации - хранить стек в каждом указателе образов. В следующем фрагменте предполагается, что у вас имеется параметризованный класс Stack с функциями Empty(), Push(), Pop() и DeleteAll(). Функция Pop() возвращает верхний элемент стека или NULL, если стек пуст. Функция DeleteAll() опустошает стек и уничтожает все объекты по мере их извлечения. Каждый указатель хранит стек предыдущих образов. Если стек пуст, значит, образы не создавались. Если стек не пуст, в его нижней части находится исходный объект. Функция Rollback() находит и восстанавливает этот объект. Конструктор копий и оператор = работают так же, как и в описанном выше простейшем указателе образов. template <class Type> class ImageStackPtr { private: Type* current; // Текущий образ, предоставляемый клиенту Stack<Type> history; // Предыдущие образы public: ImageStackPtr() : current(new Type) {} ImageStackPtr(const ImageStackPtr<Type>& ip) : current(new Type(*(ip.current))) {} ~ImageStackPtr() { delete current; } ImageStackPtr<Type>& operator=(const ImageStackPtr<Type>& ip) { if (this != &ip) { history.DeleteAll(); delete current; current = new Type(*(ip.current)); } return *this; } void PushImage() { history.Push(current); current = new Type(*current); } void Commit() { history.DeleteAll(); } void PopImage() // Вернуться на один уровень { if (!history.Empty()) { delete current; current = history.Pop(); } } void Rollback() // Вернуться к самому старому образу { Type* old = history.Pop(); Type* oldere = NULL; if (old != NULL) { // Хотя бы один раз while ((older = history.Pop()) != NULL) { delete old; old = older; } delete current; current = old; } } Type* operator->() const { return current; } }; Хранение отдельного стека в каждом указателе оправданно для транзакций, в которых участвует небольшое количество объектов. Но если одной транзакции приходится отслеживать множество обновляемых объектов, кучу мелких стеков лучше объединить в один большой. Мы сделаем это позднее, когда речь пойдет о транзакциях. |
Copyright 2005. Климов Александр. All Right Reserved.