Паттерн «Хранитель» (Memento). Описание и реализация

Хранитель (англ. Memento) — поведенческий шаблон проектирования, позволяющий, не нарушая инкапсуляцию, зафиксировать и сохранить внутреннее состояние объекта так, чтобы позднее восстановить его в это состояние [1].

Обычно используется, когда необходимо сделать «снимок» состояния некоторого объекта для его точного восстановления в будущем. Также его рекомендуется использовать, если получение состояния объекта напрямую нарушает его инкапсуляцию.

Паттерн включает три элемента:

  • Memento (хранитель).
    • Сохраняет внутреннее состояние объекта Originator («хозяин»). Объём и формат данных о состоянии при этом не регламентируется и определяется исходя из потребности;
    • Запрещает доступ к нему любых объектов кроме «хозяина».
  • Originator (хозяин).
    • Создаёт «хранитель», содержащий снимок своего внутреннего состояния;
    • Использует «хранитель» для восстановления своего внутреннего состояния.
  • Caretaker (механизм отката или посыльный).
    • Отвечает за сохранение «хранителя»;
    • Не производит над «хранителем» никаких операций и не исследует его содержимое.

Ниже показана диаграмма классов паттерна «Хранитель».

Диаграмма паттерна Memento

Механизм работы паттерна «Хранитель» достаточно прост.

Объект «хозяин» имеет некоторое состояние (может даже инициализироваться с некоторым начальным состоянием). Это состояние он сохраняет в объекте «механизм отката» для последующего восстановления в случае необходимости.

Рассмотрим работу паттерна «Хранитель» на конкретных примерах, написанных на языках программирования Delphi и Java.

Реализация
Пример на Delphi:

В Delphi доступ к данным хранящимся в классе можно легко организовать при помощи свойств, заменив ими соответствующие «геттеры» и «сеттеры». Это позволяет немного упростить структуру и последующую реализацию паттерна.

Элементы паттерна реализованные на Delphi:

Ниже приведён пример его работы:

 Пример на Java:

В Java отсутствует механизм свойств в привычном виде. Вместо этого используются только «геттеры» и «сеттеры».

Java также поддерживает открытые поля класса. Но, прямой доступ к полям класса, как известно, является нарушением инкапсуляции. Поэтому использовать их в реализации не рекомендуется.

Перепишем приведённый выше пример на Java. Элементы паттерна примут следующий вид.

«Хранитель»:

 «Механизм отката»:

 «Хозяин»:

Соответственно работа паттерна:

 Паттерны «Хранитель» и «Состояние»

Паттерн «Хранитель» при определённых условиях также как и паттерн «Состояние» способен изменять поведение объекта. Но, в отличие от последнего он не ставит изменение логики работы своей основной целью. Данная возможность скорее «побочный эффект».

Главная задача паттерна «Хранитель» сохранить и при необходимости восстановить текущее состояние объекта на момент создания «хранителя».

Однако всё вышесказанное вовсе не исключает возможность совместной реализации обоих паттернов. Ведь «хранитель» может сохранить практически любые данные. Объект «состояние» [2] не является исключением.

Таким образом, открывается возможность сохранять не только данные, но и сами алгоритмы работы. Что при умелом подходе позволяет существенно расширить возможности разрабатываемого программного обеспечения и сделать его работу более гибкой.

Источники:

  1. Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. Приёмы объектно-ориентированного проектирования. Паттерны проектирования.
  2. Стрелец Coder. Паттерн «Состояние» (State). Описание и пример реализации.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *