备忘录模式(Memento Pattern)是一种行为设计模式,用于捕获对象的内部状态并在需要时恢复该状态,同时不破坏对象的封装性。它适用于需要实现撤销/重做、历史记录或状态快照的场景。
核心组件
Originator(原发器)
- 需要保存状态的对象
- 提供创建备忘录和恢复状态的方法
- 示例代码:
public class TextEditor { private String content; public void write(String text) { this.content = text; } // 创建备忘录 public TextMemento save() { return new TextMemento(content); } // 从备忘录恢复 public void restore(TextMemento memento) { this.content = memento.getSavedContent(); } }
Memento(备忘录)
- 存储 Originator 的内部状态
- 通常设计为不可变对象
- 示例代码:
public final class TextMemento { private final String content; public TextMemento(String content) { this.content = content; } // 仅允许原发器访问 String getSavedContent() { return content; } }
Caretaker(管理者)
- 负责保存和管理备忘录
- 不能修改备忘录内容
- 示例代码:
import java.util.Stack; public class History { private final Stack<TextMemento> states = new Stack<>(); public void saveState(TextMemento state) { states.push(state); } public TextMemento getLastState() { return states.pop(); } }
工作流程
graph LR
A[Originator] -- 创建 --> B[Memento]
B -- 存储 --> C[Caretaker]
C -- 提供 --> A
A -- 恢复状态 --> B
关键特性
封装保护
- Memento 通过私有访问控制保护状态
- Caretaker 只能存储备忘录,不能修改内容
状态管理
- 支持多级撤销:使用栈结构存储历史状态
- 状态隔离:每个备忘录独立存储对象快照
内存优化
- 增量存储:仅保存变化部分
- 懒加载:需要时再生成备忘录
适用场景
- 需要实现撤销/重做功能(如文本编辑器)
- 需要保存对象历史状态(如游戏存档)
- 需要隔离状态生成和存储逻辑
优缺点分析
优点
- 保持对象封装边界
- 简化原发器职责(SRP原则)
- 支持多状态管理
缺点
- 可能增加内存消耗
- Caretaker 需维护生命周期
- 频繁保存可能影响性能
扩展实现
// 客户端使用示例
public class Client {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
History history = new History();
editor.write("First draft");
history.saveState(editor.save()); // 保存状态1
editor.write("Revised content");
history.saveState(editor.save()); // 保存状态2
editor.restore(history.getLastState()); // 撤销到状态1
}
}
设计建议
- 对大型对象使用增量备忘录
- 通过接口约束备忘录访问权限
- 结合原型模式优化状态克隆性能
- 使用对象池管理频繁创建的备忘录