Образец сувенира - Memento pattern
В сувенирный узор это шаблон разработки программного обеспечения дающий возможность восстановить объект до предыдущего состояния (отменить через откат).
Шаблон сувенира реализован с помощью трех объектов: создатель, а смотритель и сувенир. Создатель - это некий объект, имеющий внутреннее состояние. Смотритель собирается что-то сделать с отправителем, но хочет иметь возможность отменить изменение. Смотритель сначала спрашивает у создателя памятный предмет. Затем он выполняет любую операцию (или последовательность операций), которую собирался выполнить. Чтобы вернуться к состоянию до операций, он возвращает объект-памятку отправителю. Сам сувенир - это непрозрачный объект (тот, который смотритель не может или не должен менять). При использовании этого шаблона следует проявлять осторожность, если создатель может изменить другие объекты или ресурсы - шаблон сувенира работает с одним объектом.
Классические примеры рисунка сувениров включают семя генератор псевдослучайных чисел (после этого он всегда будет производить ту же последовательность при инициализации состояние семян )[нужна цитата ][требуется разъяснение ] и государство в конечный автомат.
Обзор
Сувенир[1]шаблон дизайна - один из двадцати трех хорошо известных Шаблоны проектирования GoF в которых описывается, как решать повторяющиеся проблемы проектирования для разработки гибкого и многократно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые проще реализовать, изменить, протестировать и повторно использовать. Шаблон Memento был создан Ноа Томпсоном, Дэвидом Эспириту и доктором Дрю Клинкенбердом для ранних продуктов HP.
Какие проблемы может решить шаблон проектирования Memento?
- Внутреннее состояние объекта должно быть сохранено извне, чтобы объект можно было восстановить в это состояние позже.
- Инкапсуляция объекта не должна нарушаться.
Проблема в том, что хорошо спроектированный объект инкапсулируется так, что его представление (структура данных) скрыто внутри объекта и к нему нельзя получить доступ извне.
Какое решение описывает шаблон проектирования Memento?
Сделайте сам объект (создателя) ответственным за
- сохранение его внутреннего состояния в (памятный) объект и
- восстановление в предыдущее состояние из (памятного) объекта.
Доступ к нему имеет только автор, создавший сувенир.
Клиент (смотритель) может запросить памятный знак у отправителя (чтобы сохранить внутреннее состояние отправителя) и передать памятный знак обратно отправителю (для восстановления предыдущего состояния).
Это позволяет сохранять и восстанавливать внутреннее состояние отправителя без нарушения его инкапсуляции.
См. Также схему классов и последовательности UML ниже.
Структура
Схема классов и последовательности UML
В приведенном выше 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:
- Сериализация.
- Класс, объявленный в том же пакете.
- К объекту также можно получить доступ через прокси-сервер, который может выполнить любую операцию сохранения / восстановления объекта.
Пример 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])
Рекомендации
- ^ Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес (1994). Паттерны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования. Эддисон Уэсли. стр.283ff. ISBN 0-201-63361-2.CS1 maint: несколько имен: список авторов (связь)
- ^ «Шаблон дизайна Memento - проблема, решение и применимость». w3sDesign.com. Получено 2017-08-12.
- ^ «Шаблон дизайна Memento - структура и взаимодействие». w3sDesign.com. Получено 2017-08-12.
внешняя ссылка
- Описание Memento Pattern в Ада
- Схема классов Memento UML с примерами кода C # и .NET
- SourceMaking Учебник
- Шаблон дизайна Memento с использованием Java