printПаттерны поведения

printХранитель

Memento

Назначение
Не нарушая инкапсуляции, фиксирует и выносит за пределы объекта его внутреннее состояние так, чтобы позднее можно было восстановить в нем объект.

Результаты
1. Хранитель позволяет избежать раскрытия информации, которой должен распоряжаться только хозяин, но которую тем не менее необходимо хранить вне последнего. Этот паттерн экранирует объекты от потенциально сложного внутреннего устройства хозяина, не изменяя границы инкапсуляции.
2. При других вариантах дизайна, направленного на сохранение границ инкапсуляции, хозяин хранит внутри себя версии внутреннего состояния, которое запрашивали клиенты. Таким образом, вся ответственность за управление памятью лежит на хозяине. При перекладывании заботы о запрошенном состоянии на клиентов упрощается структура хозяина, а клиентам дается возможность не информировать хозяина о том, что они закончили работу.
3. С хранителями могут быть связаны заметные издержки, если хозяин должен копировать большой объем информации для занесения в память хранителя или если клиенты создают и возвращают хранителей достаточно часто. Если плата за инкапсуляцию и восстановление состояния хозяина велика, то этот паттерн не всегда подходит.
4. В некоторых языках сложно гарантировать, что только хозяин имеет доступ к состоянию хранителя.
5. Посыльный отвечает за удаление хранителя, однако не располагает информацией о том, какой объем информации о состоянии скрыт в нем. Поэтому нетребовательный к ресурсам посыльный может расходовать очень много памяти при работе с хранителем.

Реализация
// Хранитель сохраняет внутреннее состояние объекта Originator
// и запрещает доступ всем другим объектам, кроме хозяина
class Memento {
  int state;
  Memento(int s):state(s) {}
  friend class Originator;
public:
};
// Хозяин создает хранитель и использует его для восстановления внутреннего состояния
class Originator {
  int state;
public:
  Memento *CreateMemento() { return new Memento(state); }
  void SetMemento(Memento *m) { state=m->state; }
};
// Смотритель отвечает за сохранение хранителя
class Caretaker {
  Memento *m;
  Originator *orig;
public:
  void Action()
  { m=orig->CreateMemento();
    ...
  }
  void Undo()
  { orig->SetMemento(m);
  }
};
loading