备忘录
更新: 6/22/2025 字数: 0 字 时长: 0 分钟
定义
备忘录模式 (Memento Pattern) 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。它提供了状态恢复机制,支持撤销操作。
角色
- 发起人 (Originator):创建备忘录对象,记录当前状态
- 备忘录 (Memento):存储发起人的内部状态
- 管理者 (Caretaker):保存备忘录对象,不操作备忘录内容
- 客户端 (Client):使用发起人和管理者进行状态保存和恢复
实现
文本编辑器撤销功能
java
// 备忘录:存储编辑器状态
public class EditorMemento {
private final String content;
public EditorMemento(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
// 发起人:文本编辑器
public class TextEditor {
private String content;
public void write(String text) {
content = text;
}
public String getContent() {
return content;
}
// 创建备忘录
public EditorMemento createMemento() {
return new EditorMemento(content);
}
// 从备忘录恢复
public void restoreFromMemento(EditorMemento memento) {
content = memento.getContent();
}
}
// 管理者:保存历史状态
public class History {
private Stack<EditorMemento> history = new Stack<>();
public void save(EditorMemento memento) {
history.push(memento);
}
public EditorMemento undo() {
if (!history.isEmpty()) {
return history.pop();
}
return null;
}
}
// 客户端使用
public class TextEditorDemo {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
History history = new History();
// 编辑并保存状态
editor.write("第一版内容");
history.save(editor.createMemento());
// 修改内容
editor.write("第二版内容");
history.save(editor.createMemento());
// 修改内容
editor.write("第三版内容");
System.out.println("当前内容:" + editor.getContent());
// 撤销到上一版本
editor.restoreFromMemento(history.undo());
System.out.println("撤销后内容:" + editor.getContent());
// 再次撤销
editor.restoreFromMemento(history.undo());
System.out.println("撤销两次后内容:" + editor.getContent());
}
}
游戏存档系统
java
// 游戏状态
public class GameState {
private int level;
private int score;
private String position;
public GameState(int level, int score, String position) {
this.level = level;
this.score = score;
this.position = position;
}
public int getLevel() {
return level;
}
public int getScore() {
return score;
}
public String getPosition() {
return position;
}
@Override
public String toString() {
return "Level: " + level + ", Score: " + score + ", Position: " + position;
}
}
// 备忘录:存储游戏状态
public class GameMemento {
private final GameState state;
public GameMemento(GameState state) {
this.state = state;
}
public GameState getState() {
return state;
}
}
// 发起人:游戏
public class Game {
private GameState currentState;
public Game() {
this.currentState = new GameState(1, 0, "起始点");
}
public void play(int scoreIncrease, String newPosition) {
System.out.println("游戏进行中...");
currentState = new GameState(
currentState.getLevel(),
currentState.getScore() + scoreIncrease,
newPosition
);
}
public void levelUp() {
System.out.println("升级!");
currentState = new GameState(
currentState.getLevel() + 1,
currentState.getScore(),
currentState.getPosition()
);
}
public GameState getState() {
return currentState;
}
// 创建存档
public GameMemento save() {
return new GameMemento(currentState);
}
// 加载存档
public void load(GameMemento memento) {
this.currentState = memento.getState();
}
}
// 管理者:存档管理器
public class SaveManager {
private Map<String, GameMemento> saves = new HashMap<>();
public void saveGame(String slot, GameMemento memento) {
saves.put(slot, memento);
}
public GameMemento loadGame(String slot) {
return saves.get(slot);
}
}
// 使用示例
public class GameDemo {
public static void main(String[] args) {
Game game = new Game();
SaveManager saveManager = new SaveManager();
// 初始状态
System.out.println("初始状态:" + game.getState());
// 游戏进行
game.play(100, "森林");
game.levelUp();
System.out.println("状态 1: " + game.getState());
// 保存存档 1
saveManager.saveGame("slot1", game.save());
// 继续游戏
game.play(200, "城堡");
game.levelUp();
System.out.println("状态 2: " + game.getState());
// 保存存档 2
saveManager.saveGame("slot2", game.save());
// 加载存档 1
game.load(saveManager.loadGame("slot1"));
System.out.println("加载存档 1: " + game.getState());
// 加载存档 2
game.load(saveManager.loadGame("slot2"));
System.out.println("加载存档 2: " + game.getState());
}
}
优缺点
优点:
- 提供状态恢复机制
- 实现撤销操作
- 保持封装边界
- 简化发起人代码
- 支持历史快照
- 支持事务回滚
缺点:
- 消耗内存资源
- 管理器可能复杂
- 状态存储效率问题
- 可能暴露实现细节
- 增加系统复杂度
应用场景
- 文本编辑器撤销功能
- 游戏存档系统
- 数据库事务管理
- 软件配置管理
- 浏览器历史记录
- 工作流状态恢复
- 版本控制系统
与其他模式的关系
- 与命令模式:配合实现撤销/重做
- 与原型模式:备忘录可存储原型状态
- 与状态模式:备忘录保存状态历史
- 与迭代器模式:遍历历史状态
- 与代理模式:保护备忘录访问
- 与享元模式:共享历史状态
JDK 中的备忘录模式
- Java 序列化机制
- Java 事务 API(JTA)
- Java 对象持久化(JPA)
- Java Swing 撤销框架(UndoManager)
- Java Beans 持久化
- Spring 框架的事务管理
- Java 状态管理(javax.faces.component.StateHolder)
注意事项
- 状态存储策略(完整 vs 增量)
- 内存管理(清理旧状态)
- 状态序列化格式
- 安全考虑(加密敏感状态)
- 性能优化(懒加载状态)
- 支持深拷贝与浅拷贝
- 处理状态版本兼容