【备忘录模式】

114 阅读3分钟

定义

备忘录模式(Memento Pattern)是一种行为型设计模式,它在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

以下是备忘录模式的主要特点和定义:

主要角色

  1. Originator(原发器)

    • 创建一个备忘录,用以记录当前时刻它的内部状态。
    • 使用备忘录恢复内部状态。
  2. Memento(备忘录)

    • 存储原发器的内部状态。
    • 防止原发器以外的其他对象访问备忘录。
  3. Caretaker(负责人)

    • 负责保存好备忘录。
    • 不能对备忘录的内容进行操作或检查。

业务

假设我们正在开发一个文本编辑器,用户可以在编辑器中输入文本,并且可以随时撤销和恢复操作。我们可以使用备忘录模式来实现这个功能。

classDiagram
    class TextEditor {
        -StringBuilder text
        +appendText(String) : void
        +save() : Memento
        +restore(Memento) : void
        +getText() : String
    }
    class Memento {
        -String text
        +Memento(String)
        +getText() : String
    }
    class Caretaker {
        -Memento memento
        +saveMemento(Memento) : void
        +getMemento() : Memento
    }
    TextEditor --> Memento
    Caretaker "1" --> "1" Memento

一、定义原发器(Originator) 首先定义文本编辑器类作为原发器:

class TextEditor {
    private StringBuilder text = new StringBuilder();

    public void appendText(String newText) {
        text.append(newText);
    }

    public Memento save() {
        return new Memento(text.toString());
    }

    public void restore(Memento memento) {
        text = new StringBuilder(memento.getText());
    }

    public String getText() {
        return text.toString();
    }
}

二、定义备忘录(Memento) 创建备忘录类来存储文本编辑器的状态:

class Memento {
    private final String text;

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

    public String getText() {
        return text;
    }
}

三、定义负责人(Caretaker) 负责人类负责保存和管理备忘录:

class Caretaker {
    private Memento memento;

    public void saveMemento(Memento memento) {
        this.memento = memento;
    }

    public Memento getMemento() {
        return memento;
    }
}

四、使用备忘录模式

public class MementoPatternExample {
    public static void main(String[] args) {
        TextEditor textEditor = new TextEditor();
        Caretaker caretaker = new Caretaker();

        textEditor.appendText("Hello, ");
        System.out.println("Current text: " + textEditor.getText());

        // Save state
        caretaker.saveMemento(textEditor.save());

        textEditor.appendText("world!");
        System.out.println("Current text: " + textEditor.getText());

        // Undo
        textEditor.restore(caretaker.getMemento());
        System.out.println("After undo: " + textEditor.getText());
    }
}

在这个例子中,TextEditor是原发器,它可以保存当前的文本状态到备忘录中,也可以从备忘录中恢复之前的状态。Memento是备忘录类,用于存储文本编辑器的状态。Caretaker是负责人类,负责保存和管理备忘录。通过这种方式,我们实现了文本编辑器的撤销和恢复功能,同时保持了原发器的封装性,外部类无法直接访问文本编辑器的内部状态。

总结

使用场景

  1. 需要保存一个对象在某个时刻的内部状态,以便在需要的时候恢复到这个状态。

    • 例如在游戏中,可以使用备忘录模式保存游戏角色的状态,以便在玩家需要时恢复到之前的状态。
  2. 实现撤销操作。

    • 当用户执行一个操作后,可以创建一个备忘录来保存操作前的状态,以便在需要撤销时恢复到这个状态。

优点

  1. 保持了封装性。

    • 原发器不需要暴露自己的内部状态给其他对象,只有通过备忘录才能访问和恢复其状态。
  2. 简化了原发器的设计。

    • 原发器不需要管理和保存自己的历史状态,这些工作由备忘录和负责人来完成。

缺点

  1. 如果原发器的内部状态过多,或者状态变化频繁,可能会导致备忘录对象非常庞大,占用大量的内存空间。
  2. 备忘录模式可能会增加系统的复杂性,特别是在需要管理多个备忘录对象的情况下。