Skip to main content

备忘录模式 (Memento)

场景问题​

问题案例​

考虑一个文本编辑器,用户可以随时撤销(undo)和恢复(redo)编辑操作,需要保存历史状态。

不用模式的解决方案​

实现简化版本​

最直接的做法是用一个列表保存所有历史文本:

public class Editor {
private List<String> history = new ArrayList<>();
private String text = "";
public void setText(String newText) {
history.add(text);
text = newText;
}
public void undo() {
if (!history.isEmpty()) {
text = history.remove(history.size() - 1);
}
}
public String getText() { return text; }
}

使用示例​

Editor editor = new Editor();
editor.setText("Hello");
editor.setText("Hello, World");
editor.undo();
System.out.println(editor.getText());

有何问题​

  1. 只能保存简单状态,难以扩展。
  2. 状态管理与编辑器逻辑混杂,职责不清。
  3. 不能灵活保存和恢复多种类型的状态。

解决方案​

备忘录模式的定义​

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

应用备忘录模式的思路​

  • 定义备忘录类,封装需要保存的状态。
  • 发起人创建和恢复备忘录。
  • 管理者负责保存和管理备忘录对象。

备忘录模式的结构​

  • Originator:发起人,创建和恢复备忘录。
  • Memento:备忘录,封装状态。
  • Caretaker:管理者,保存和管理备忘录。

备忘录模式的实现​

// 备忘录
public class Memento {
private String state;
public Memento(String state) { this.state = state; }
public String getState() { return state; }
}

// 发起人
public class Editor {
private String text = "";
public void setText(String text) { this.text = text; }
public String getText() { return text; }
public Memento createMemento() { return new Memento(text); }
public void restoreMemento(Memento m) { this.text = m.getState(); }
}

// 管理者
public class Caretaker {
private List<Memento> history = new ArrayList<>();
public void addMemento(Memento m) { history.add(m); }
public Memento getMemento() {
if (!history.isEmpty()) {
return history.remove(history.size() - 1);
}
return null;
}
}

使用示例​

public class Client {
public static void main(String[] args) {
Editor editor = new Editor();
Caretaker caretaker = new Caretaker();
editor.setText("Hello");
caretaker.addMemento(editor.createMemento());
editor.setText("Hello, World");
caretaker.addMemento(editor.createMemento());
editor.setText("Hello, Java");
editor.restoreMemento(caretaker.getMemento());
System.out.println(editor.getText()); // 输出 Hello, World
editor.restoreMemento(caretaker.getMemento());
System.out.println(editor.getText()); // 输出 Hello
}
}

备忘录重写示例​

示例结构​


示例代码​

见上文"备忘录模式的实现"部分。


模式讲解​

备忘录模式的功能​

  • 实现对象状态的保存与恢复。
  • 不破坏对象封装性。
  • 支持多次撤销、恢复。

实现成接口​

  • 备忘录和发起人通常定义为类,也可用接口。

使用工厂方法​

  • 可结合工厂方法模式,统一创建备忘录对象。

切换产品簇​

  • 可用于切换不同的状态保存方案,如多文档编辑器。

执行时序图​