Стеки образов
Вторник, 27 Июль 2010 6:41Для многоуровневой отмены вам может понадобиться стек предыдущих образов. Один из вариантов реализации — хранить стек в каждом указателе образов. В следующем фрагменте предполагается, что у вас имеется параметризованный класс Stack с функциями EmptyO, PushQ, PopO и DeleteAll (). Функция РорО возвращает верхний элемент стека или null, если стек пуст. Функция DeleteAll () опустошает стек и уничтожает все объекты по мере их извлечения.
Каждый указатель хранит стек предыдущих образов. Если стек пуст, значит, образы не создавались. Если стек не пуст, в его нижней части находится исходный объект. Функция Roll back () находит и восстанавливает этот объект. Конструктор копий и оператор = работают так же, как и в описанном выше простейшем указателе образов.
template <class туре> class imageStackPtr { private:
туре* current; // текущий образ, предоставляемый клиенту Stack<Type> history; // предыдущие образы public:
imageStackPtr() : current(new туре) {} imageStackPtr(const imageStackPtr<Type>& ip)
: current(new Type(*(ip.current))) {} ~imageStackPtr() { delete current; }
imageStackPtr<Type>& operator=(const imageStackPtr<Type>& ip) {
if (this != &ip) {
hi story.DeleteAll(); delete current;
current = new Type(*(ip.current)); }
return *this; }
void PushimageQ {
history.Push(current); current = new Type(*current); }
void CommitO { hi story. Del eteAl 1 (); } void PopimageQ // вернуться на один уровень {
if (Ihistory.EmptyO) { delete current; current = history.PopO ;
void RollbackQ // вернуться к самому старому образу {
туре* old = hi story. Pop () ;
туре* oldere = null;
if (old != null) { // хотя бы один раз
while ((older = history. PopO) != null) { delete old; old = older; }
delete current; current = old;
туре* operator->() const { return current; }
Хранение отдельного стека в каждом указателе оправданно для транзакций, в которых участвует небольшое количество объектов. Но если одной транзакции приходится отслеживать множество обновляемых объектов, кучу мелких стеков лучше объединить в один большой. Мы сделаем это позднее, когда речь пойдет о транзакциях.