Образец сувенира - Memento pattern

В сувенирный узор это шаблон разработки программного обеспечения дающий возможность восстановить объект до предыдущего состояния (отменить через откат).

Шаблон сувенира реализован с помощью трех объектов: создатель, а смотритель и сувенир. Создатель - это некий объект, имеющий внутреннее состояние. Смотритель собирается что-то сделать с отправителем, но хочет иметь возможность отменить изменение. Смотритель сначала спрашивает у создателя памятный предмет. Затем он выполняет любую операцию (или последовательность операций), которую собирался выполнить. Чтобы вернуться к состоянию до операций, он возвращает объект-памятку отправителю. Сам сувенир - это непрозрачный объект (тот, который смотритель не может или не должен менять). При использовании этого шаблона следует проявлять осторожность, если создатель может изменить другие объекты или ресурсы - шаблон сувенира работает с одним объектом.

Классические примеры рисунка сувениров включают семя генератор псевдослучайных чисел (после этого он всегда будет производить ту же последовательность при инициализации состояние семян )[нужна цитата ][требуется разъяснение ] и государство в конечный автомат.

Обзор

Сувенир[1]шаблон дизайна - один из двадцати трех хорошо известных Шаблоны проектирования GoF в которых описывается, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые проще реализовать, изменить, протестировать и повторно использовать. Шаблон Memento был создан Ноа Томпсоном, Дэвидом Эспириту и доктором Дрю Клинкенбердом для ранних продуктов HP.

Какие проблемы может решить шаблон проектирования Memento?

[2]

  • Внутреннее состояние объекта должно быть сохранено извне, чтобы объект можно было восстановить в это состояние позже.
  • Инкапсуляция объекта не должна нарушаться.

Проблема в том, что хорошо спроектированный объект инкапсулируется так, что его представление (структура данных) скрыто внутри объекта и к нему нельзя получить доступ извне.

Какое решение описывает шаблон проектирования Memento?

Сделайте сам объект (создателя) ответственным за

  • сохранение его внутреннего состояния в (памятный) объект и
  • восстановление в предыдущее состояние из (памятного) объекта.

Доступ к нему имеет только автор, создавший сувенир.

Клиент (смотритель) может запросить памятный знак у отправителя (чтобы сохранить внутреннее состояние отправителя) и передать памятный знак обратно отправителю (для восстановления предыдущего состояния).

Это позволяет сохранять и восстанавливать внутреннее состояние отправителя без нарушения его инкапсуляции.

См. Также схему классов и последовательности UML ниже.

Структура

Схема классов и последовательности UML

Пример класса UML и диаграмма последовательности для шаблона проектирования Memento. [3]

В приведенном выше UML диаграмма классов, то Смотритель класс относится к Автор класс для сохранения (createMemento ()) и восстановление (восстановить (сувенир)) внутреннее состояние отправителя.
В Автор класс реализует
(1) createMemento () создавая и возвращая Memento объект, который хранит текущее внутреннее состояние отправителя и
(2) восстановить (сувенир) путем восстановления состояния из переданного в Memento объект.

В UML схема последовательности показывает взаимодействия во время выполнения:
(1) Сохранение внутреннего состояния отправителя: Смотритель вызовы объектов createMemento () на Автор объект, который создает Memento объект, сохраняет свое текущее внутреннее состояние (setState ()) и возвращает Memento к Смотритель.
(2) Восстановление внутреннего состояния отправителя: Смотритель звонки восстановить (сувенир) на Автор объект и указывает Memento объект, в котором хранится состояние, которое необходимо восстановить. В Автор получает состояние (getState ()) от Memento установить собственное состояние.

Пример Java

Следующее Ява Программа иллюстрирует "отмену" использования шаблона памятного знака.

импорт java.util.List;импорт java.util.ArrayList;учебный класс Автор {    частный Нить государственный;    // Класс также может содержать дополнительные данные, которые не являются частью    // состояние сохранено в памятке ..     общественный пустота набор(Нить государственный) {        это.государственный = государственный;        Система.из.println("Создатель: установка состояния" + государственный);    }     общественный Memento saveToMemento() {        Система.из.println(«Создатель: Сохранение на память».);        возвращаться новый Memento(это.государственный);    }     общественный пустота restoreFromMemento(Memento сувенир) {        это.государственный = сувенир.getSavedState();        Система.из.println("Создатель: состояние после восстановления из Memento:" + государственный);    }     общественный статический учебный класс Memento {        частный окончательный Нить государственный;        общественный Memento(Нить stateToSave) {            государственный = stateToSave;        }         // доступно только внешнему классу        частный Нить getSavedState() {            возвращаться государственный;        }    }} учебный класс Смотритель {    общественный статический пустота главный(Нить[] аргументы) {        Список<Автор.Memento> saveStates = новый ArrayList<Автор.Memento>();         Автор создатель = новый Автор();        создатель.набор("State1");        создатель.набор("State2");        saveStates.Добавить(создатель.saveToMemento());        создатель.набор("State3");        // Мы можем запросить несколько памятных вещей и выбрать, к какому из них откатиться.        saveStates.Добавить(создатель.saveToMemento());        создатель.набор("State4");         создатель.restoreFromMemento(saveStates.получать(1));       }}

Результат:

Originator: установка состояния на State1Originator: установка состояния на State2Originator: сохранение в Memento.Originator: установка состояния на State3Originator: сохранение в Memento.Originator: установка состояния на State4Originator: состояние после восстановления из Memento: State3

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

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

Есть три других способа получить Memento:

  1. Сериализация.
  2. Класс, объявленный в том же пакете.
  3. К объекту также можно получить доступ через прокси-сервер, который может выполнить любую операцию сохранения / восстановления объекта.

Пример C #

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

учебный класс Memento{    частный только чтение нить saveState;    частный Memento(нить stateToSave)    {        saveState = stateToSave;    }    общественный учебный класс Автор    {        частный нить государственный;        // Класс также может содержать дополнительные данные, которые не являются частью        // состояние сохранено в памятке.        общественный пустота Набор(нить государственный)        {            Консоль.WriteLine("Создатель: установка состояния" + государственный);            это.государственный = государственный;        }        общественный Memento SaveToMemento()        {            Консоль.WriteLine(«Создатель: Сохранение на память».);            возвращаться новый Memento(государственный);        }        общественный пустота RestoreFromMemento(Memento сувенир)        {            государственный = сувенир.saveState;            Консоль.WriteLine("Создатель: состояние после восстановления из Memento:" + государственный);        }    }}учебный класс Смотритель{    статический пустота Главный(нить[] аргументы)    {        Список<Memento> saveStates = новый Список<Memento>();        Memento.Автор создатель = новый Memento.Автор();        создатель.Набор("State1");        создатель.Набор("State2");        saveStates.Добавлять(создатель.SaveToMemento());        создатель.Набор("State3");        // Мы можем запросить несколько памятных вещей и выбрать, к какому из них откатиться.        saveStates.Добавлять(создатель.SaveToMemento());        создатель.Набор("State4");        создатель.RestoreFromMemento(saveStates[1]);    }}

Пример Python

"""Пример рисунка на память."""учебный класс Memento:    def __в этом__(себя, государственный) -> Никто:        себя._государственный = государственный    def get_saved_state(себя):        возвращаться себя._государственныйучебный класс Автор:    _государственный = ""    def набор(себя, государственный) -> Никто:        Распечатать("Создатель: установка состояния", государственный)        себя._государственный = государственный    def save_to_memento(себя) -> Memento:        Распечатать(«Создатель: Сохранение на память».)        возвращаться Memento(себя._государственный)    def restore_from_memento(себя, сувенир) -> Никто:        себя._государственный = сувенир.get_saved_state()        Распечатать("Создатель: состояние после восстановления из Memento:", себя._государственный)save_states = []создатель = Автор()создатель.набор("State1")создатель.набор("State2")save_states.добавить(создатель.save_to_memento())создатель.набор("State3")save_states.добавить(создатель.save_to_memento())создатель.набор("State4")создатель.restore_from_memento(save_states[1])

Рекомендации

  1. ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования. Эддисон Уэсли. стр.283ff. ISBN  0-201-63361-2.CS1 maint: несколько имен: список авторов (связь)
  2. ^ «Шаблон дизайна Memento - проблема, решение и применимость». w3sDesign.com. Получено 2017-08-12.
  3. ^ «Шаблон дизайна Memento - структура и взаимодействие». w3sDesign.com. Получено 2017-08-12.

внешняя ссылка