Рубрики
Без рубрики

Шаблон дизайна Memento в Java

Узнайте все о шаблоне дизайна Memento в Java

Автор оригинала: François Dupire.

1. Обзор

В этом уроке мы узнаем, что такое шаблон дизайна Memento и как его использовать.

Сначала мы немного пройдемся по теории. Затем мы создадим пример, в котором проиллюстрируем использование шаблона.

2. Что такое шаблон дизайна сувенира?

Паттерн дизайна сувениров, описанный “Бандой четырех” в своей книге , является поведенческим паттерном дизайна. Шаблон дизайна Memento предлагает решение для реализации неустранимых действий. Мы можем сделать это, сохранив состояние объекта в данный момент и восстановив его, если действия, выполненные с тех пор, должны быть отменены.

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

Объект Memento должен предоставлять Хранителю как можно меньше информации. Это делается для того, чтобы мы не открывали внешнему миру внутреннее состояние Создателя, так как это нарушило бы принципы инкапсуляции. Однако Создатель должен получить доступ к достаточному количеству информации, чтобы восстановить исходное состояние.

Давайте рассмотрим краткую диаграмму классов, иллюстрирующую, как различные объекты взаимодействуют друг с другом:

Как мы видим, Создатель может производить и потреблять Сувенир. Между тем Смотритель только сохраняет состояние, прежде чем восстановить его. Внутреннее представление Создателя скрыто от внешнего мира.

Здесь мы использовали одно поле для представления состояния Отправителя, хотя мы не ограничены одним полем и могли бы использовать столько полей, сколько необходимо . Кроме того, состояние, содержащееся в объекте Memento, не обязательно должно соответствовать полному состоянию Отправителя. До тех пор, пока сохраненная информация достаточна для восстановления состояния Отправителя, мы готовы идти.

3. Когда использовать шаблон дизайна Memento?

Как правило, шаблон дизайна Memento будет использоваться в ситуациях, когда некоторые действия невозможно отменить, поэтому требуется откат к предыдущему состоянию. Однако, если состояние Оригинатора тяжелое, использование шаблона дизайна Memento может привести к дорогостоящему процессу создания и увеличению использования памяти.

4. Пример шаблона Memento

4.1. Исходная выборка

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

public class TextEditor {

    private TextWindow textWindow;

    public TextEditor(TextWindow textWindow) {
        this.textWindow = textWindow;
    }
}

Он имеет текстовое окно, которое содержит введенный в данный момент текст и предоставляет возможность добавить больше текста:

public class TextWindow {

    private StringBuilder currentText;

    public TextWindow() {
        this.currentText = new StringBuilder();
    }

    public void addText(String text) {
        currentText.append(text);
    }
}

4.2. Сувенир

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

Для этого мы воспользуемся шаблоном дизайна Memento. Сначала мы создадим объект, содержащий текущий текст окна:

public class TextWindowState {

    private String text;

    public TextWindowState(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }
}

Этот предмет-наша память. Как мы видим, мы решили использовать String вместо StringBuilder , чтобы предотвратить любое обновление текущего текста посторонними.

4.3. Составитель

После этого мы должны будем предоставить Текстовое окно класс с методами для создания и использования объекта Memento, что делает Текстовое окно наш Создатель:

public TextWindowState save() {
    return new TextWindowState(wholeText.toString());
}

public void restore(TextWindowState save) {
    currentText = new StringBuilder(save.getText());
}

Метод save() позволяет нам создать объект, в то время как метод restore() использует его для восстановления предыдущего состояния.

4.4. Смотритель

Наконец, мы должны обновить наш Текстовый редактор класс. Как Смотритель, он будет удерживать состояние Создателя и просить восстановить его при необходимости:

private TextWindowState savedTextWindow;

public void hitSave() {
    savedTextWindow = textWindow.save();
}

public void hitUndo() {
    textWindow.restore(savedTextWindow);
}

4.5. Тестирование решения

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

TextEditor textEditor = new TextEditor(new TextWindow());
textEditor.write("The Memento Design Pattern\n");
textEditor.write("How to implement it in Java?\n");
textEditor.hitSave();
 
textEditor.write("Buy milk and eggs before coming home\n");
 
textEditor.hitUndo();

assertThat(textEditor.print()).isEqualTo("The Memento Design Pattern\nHow to implement it in Java?\n");

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

5. Заключение

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

Полный код, используемый в этой статье, можно найти на GitHub .