Skip to content

备忘录模式解决"保存和恢复对象状态"的问题——不破坏封装的前提下,把对象状态存成快照,需要时回滚。编辑器的撤销、游戏的存档就是它的场景。这篇讲清它怎么保存/恢复状态。

一、解决什么问题:保存和恢复状态

编辑器要支持"撤销"——把文档从当前状态回退到上一步。但对象的内部状态(字段)通常被封装保护,外部不能随便读。

备忘录模式:对象自己生成一个"状态快照"(备忘录),外部只负责保存快照,需要时用快照恢复

二、核心结构

java
// 备忘录:保存对象的状态快照(不可变,只有原对象能读懂)
class EditorMemento {
    private final String content;   // 快照内容
    EditorMemento(String content) { this.content = content; }
    String getContent() { return content; }
}

// 发起人:编辑器,能创建快照、恢复快照
class Editor {
    private String content = "";

    void type(String text) { content += text; }

    EditorMemento save() { return new EditorMemento(content); }   // 创建快照

    void restore(EditorMemento m) { this.content = m.getContent(); }  // 恢复

    String getContent() { return content; }
}

// 管理者:只保存快照,不动内容
class History {
    private Deque<EditorMemento> stack = new ArrayDeque<>();   // 撤销栈
    void push(EditorMemento m) { stack.push(m); }
    EditorMemento pop() { return stack.pop(); }
}

// 使用:编辑 → 存快照 → 撤销 = 恢复上一个快照
Editor editor = new Editor();
editor.type("hello");
History history = new History();
history.push(editor.save());   // 存快照 1

editor.type(" world");
history.push(editor.save());   // 存快照 2

editor.restore(history.pop()); // 撤销 → 回到快照 1("hello")

关键EditorMemento 是快照,Editor 自己能创建和恢复它,History 只负责存(不碰内容)。这样既保存了状态,又不破坏 Editor 的封装。

三、核心价值

  • 不破坏封装:状态快照由对象自己生成,外部存/取不碰内部字段
  • 支持撤销/回滚:用栈存快照,pop 就能回退

四、实际应用

  • 编辑器撤销:Ctrl+Z = 弹出上一个快照恢复
  • 游戏存档:存档 = 保存状态快照,读档 = 恢复
  • 事务回滚:出错时恢复到之前的状态

小结

  • 备忘录 = 对象状态快照,支持保存/恢复
  • 快照由对象自己生成,不破坏封装
  • 典型:编辑器撤销、游戏存档、事务回滚

相关:《命令模式》(命令的 undo 常配合备忘录存快照,两者常一起用实现撤销)。