Сегодня мы запускаем еще один шаблон проектирования, он называется Memento, это очень простой для понимания шаблон, также основной рисунок в этой статье также переводит шаблон, в то же время очень привлекающий внимание :) в основном это означает, что вы можете восстановить состояние объекта к предыдущему, точнее схема объяснена далее в статье :)
Обсуждение
Основная цель шаблона Memento - сохранить внутреннее состояние объекта и возможность его восстановления при необходимости без нарушения инкапсуляции.
Реализация этого паттерна состоит в основном из трех классов:
Originator- класс, который сохраняет и восстанавливает состояние объекта.
Смотритель - класс, который хранит все состояния объекта, с которым он работает, возвращает эти состояния и добавляет новые состояния объекта.
Memento- класс, в котором хранится текущее состояние объекта, его состояние может быть прочитано классом Originator.
Отличным примером использования шаблона Memento является, например, восстановление предыдущих версий плагинов в wordpress, если вы использовали wordpress и у вас был установлен плагин WP Rollback, это была новая кнопка рядом с названием плагина Откат , который используется для восстановления предыдущей версии плагина, как показано на рисунке ниже.
Создатели этого плагина использовали паттерн Memento на 100% :) Memento также используется в играх, когда игрок хочет загрузить предыдущее состояние ранее сохраненной игры.
Намерение
- Сохранение внутреннего состояния объекта и, при необходимости, восстановление ранее сохраненного состояния объекта.
- Отсутствие нарушения инкапсуляции объекта, над которым мы работаем.
Проблема
Проблема, в которой вы используете шаблон памятки, очень проста :) вы хотите выполнить функцию для сохранения и загрузки состояния игры или создать механизм для восстановления вашей программы, которую, как мы предполагаем, вы сейчас создаете для предыдущей версии, в этом случае лучше всего использовать сувенир :)
Эти зрелые люди знают, что происходит на картинке выше 😂😂
Используйте, когда:
- Вам необходимо восстановить состояние объекта до его предыдущего состояния.
Структура
UML-диаграмма паттерна сувениров выглядит так:
Объяснение работы этих классов уже есть в разделе Обсуждение вверху статьи, так что мне, наверное, не придется повторяться :)
Я знаю, ты очень умный
Впрочем, пора перейти к коду :) Для реальной работы :)
Начнем с класса Memento.
namespace MementoScheme { class Memento { private string state; public Memento(string state) { this.state = state; } public string getState() { return state; } } }
Как видите, этот класс, как объяснялось ранее, хранит и возвращает текущее состояние объекта.
Смотритель класс.
namespace MementoScheme { class Caretaker { private List<Memento> mementos = new List<Memento>(); public void addMemento(Memento m) { mementos.Add(m); } public Memento getMemento(int index) { return mementos[index]; } } }
И класс Originator.
namespace MementoScheme { class Originator { private string state; public void setState(string state) { Console.WriteLine("Originator: Setting state to " + state); this.state = state; } public Memento save() { Console.WriteLine("Originator: Saving to Memento."); return new Memento(state); } public void restore(Memento m) { state = m.getState(); Console.WriteLine("Originator: State after restoring from Memento: " + state); } } }
Как уже было сказано ранее, у этого класса, как видите, есть методы, отвечающие за сохранение и восстановление состояния объекта. В методе save () нам нужно получить текущее состояние объекта, поэтому мы должны использовать класс Memento, аналогичный классу the restore () метод.
Еще раз повторяю, объяснение функции всех этих классов находится в разделе Обсуждение вверху статьи :)
Конечно, остался заказчик, который пользуется этими классами.
namespace MementoScheme { public class MementoDemo { public static void Main(String[] args) { Caretaker caretaker = new Caretaker(); Originator originator = new Originator(); originator.setState("State1"); originator.setState("State2"); caretaker.addMemento(originator.save()); originator.setState("State3"); caretaker.addMemento(originator.save()); originator.setState("State4"); originator.restore(caretaker.getMemento(1)); Console.ReadLine(); } } }
Результат:
Пример из реальной жизни
Замена тормозного барабана
Предположим, нам нужно заменить тормозной барабан в машине, и он должен сделать за нас робота.
Требуется подорвать машину и снять колесо, затем заменить тормозной барабан и вернуться в предыдущее состояние, чтобы поставить колесо и нормально поставить машину :) В роботе, который должен это сделать за нас, будет хорошо загрузить программное обеспечение с использованием выкройки Memento :) Для лучшего понимания приведена картинка ниже.
И снова к коду :) Давайте сделаем это по порядку, как в предыдущем примере :) В общем, код мне не понадобится, даже вроде как мне объяснять, потому что он практически такой же, как в предыдущем примере, только имена разные :)
Итак, мы начнем с класса Memento, в нашем случае он называется Автомобиль.
namespace Mechanic { class Car { private string state; public Car(string state) { this.state = state; } public string getState() { return state; } } }
Вы можете видеть, что так же, как и раньше, отличается только название класса :)
Смотритель класс.
namespace Mechanic { class Caretaker { private List<Car> mementos = new List<Car>(); public void addMemento(Car m) { mementos.Add(m); } public Car getMemento(int index) { return mementos[index]; } } }
Как и раньше, только имена тоже разные :)
Класс Originator в нашем случае называется Mechanic.
namespace Mechanic { class Mechanic { private string state; public void setState(string state) { Console.WriteLine(state); this.state = state; } public Car save() { return new Car(state); } public void restore(Car m) { state = m.getState(); Console.WriteLine("Returning to the previous work."); Console.WriteLine(state); } } }
Логика этого класса такая же, как и в предыдущем примере :)
И клиент :)
namespace Mechanic { class Program { static void Main(string[] args) { Caretaker caretaker = new Caretaker(); Mechanic mechanic = new Mechanic(); mechanic.setState("The brake drum is in use. Begin of work"); caretaker.addMemento(mechanic.save()); mechanic.setState("The brake drum is available to use. End of work"); mechanic.restore(caretaker.getMemento(0)); Console.ReadLine(); } } }
Результат:
Отношения с другими шаблонами проектирования
- Memento иногда используется вместе с итератором для управления состоянием итерации.
Резюме
Это все о Memento 🙂.
Ссылка на github со всем кодом из этой статьи: https://github.com/Slaw145/Memento
Этот контент вы также можете найти в моем блоге devman.pl: http://devman.pl/programtech/design-patterns-memento/
И на steemit: https://steemit.com/design-patterns/@slawas/design-patterns-memento
В следующей статье мы поговорим о шаблоне Memento.
И ОБЯЗАТЕЛЬНО присоединяйтесь к сообществу DevmanCommunity на fb, часть сообщества находится в одном месте 🙂
- сайт в фб: Devman.pl-Slawomir Kowalski
- группа в фб: DevmanCommunity
Спрашивайте, комментируйте внизу в конце поста, делитесь им, оценивайте, как хотите🙂.
Иллюстрации, изображения и диаграммы взяты с сайта: https://sourcemaking.com/design_patterns/memento