最近看到一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站
一、实现方式
- 基础结构与角色定义
备忘录模式包含三个核心角色,协作关系如下:
- Originator(发起人):需保存/恢复状态的对象,提供创建和恢复备忘录的方法。
- Memento(备忘录):存储发起人状态的载体,通常设计为不可变类。
- Caretaker(管理者):管理备忘录对象,不操作其内容。
代码示例(文本编辑器场景):
// 发起人:文本编辑器
public class Editor {
private String content;
// 创建备忘录
public Memento save() {
return new Memento(content);
}
// 从备忘录恢复状态
public void restore(Memento memento) {
this.content = memento.getState();
}
}
// 备忘录:存储状态(不可变)
public class Memento {
private final String state;
public Memento(String state) { this.state = state; }
public String getState() { return state; }
}
// 管理者:保存备忘录列表
public class History {
private List mementos = new ArrayList<>();
public void add(Memento memento) { mementos.add(memento); }
public Memento get(int index) { return mementos.get(index); }
}
- 高级实现技巧
- 多级撤销与重做:使用栈结构管理备忘录。
public class AdvancedHistory { private Stack undoStack = new Stack<>(); private Stack redoStack = new Stack<>(); public void push(Memento memento) { undoStack.push(memento); } public Memento undo() { return undoStack.pop(); } public void redo(Memento memento) { redoStack.push(memento); } }
- 资源优化:通过序列化持久化备忘录。
// 发起人支持序列化 public class SerializableOriginator extends Originator implements Serializable { private String state; }
二、测试用例设计
- 基础功能验证
目标:验证状态保存与恢复的正确性。
public class MementoTest {
@Test
public void testStateRecovery() {
Editor editor = new Editor();
History history = new History();
editor.setContent("Initial text");
history.add(editor.save()); // 保存状态1
editor.setContent("Modified text");
history.add(editor.save()); // 保存状态2
// 恢复到状态1
editor.restore(history.get(0));
assertEquals("Initial text", editor.getContent());
}
}
- 异常场景测试
目标:验证空备忘录或非法操作的容错性。
@Test(expected = IllegalStateException.class)
public void testRestoreNullMemento() {
Editor editor = new Editor();
editor.restore(null); // 触发异常
}
- 多级撤销测试
目标:验证栈结构管理的撤销/重做功能。
@Test
public void testUndoRedo() {
Editor editor = new Editor();
AdvancedHistory history = new AdvancedHistory();
editor.setContent("State 1");
history.push(editor.save());
editor.setContent("State 2");
history.push(editor.save());
// 撤销到状态1
editor.restore(history.undo());
assertEquals("State 1", editor.getContent());
// 重做到状态2
history.redo(editor.save());
assertEquals("State 2", editor.getContent());
}
- 性能与资源测试
目标:监控内存占用与优化策略有效性。
@Test
public void testMemoryOptimization() {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
// 生成1000个备忘录
for (int i = 0; i < 1000; i++) {
originator.setState("State #" + i);
caretaker.add(originator.saveStateToMemento());
}
// 断言内存占用符合预期(需结合Profiler工具)
assertTrue(memoryUsage < MAX_ALLOWED_MEMORY);
}
三、关键设计原则
- 封装性保护:
Memento
类仅对Originator
开放宽接口,其他类仅通过Caretaker
管理。
- 职责分离:
- 状态管理由
Caretaker
负责,状态逻辑由Originator
实现。
- 状态管理由
- 资源控制:
- 限制备忘录数量(如仅保存最近10个状态)或使用增量存储。
四、实际应用示例
场景:游戏存档系统
// 发起人:游戏角色
public class Gamer {
private int level;
private Inventory items;
public GamerMemento save() {
return new GamerMemento(level, items.clone());
}
public void restore(GamerMemento memento) {
this.level = memento.getLevel();
this.items = memento.getItems();
}
// 备忘录类(内部类)
public static class GamerMemento {
private final int level;
private final Inventory items;
// 构造函数与Getter
}
}
// 测试用例
@Test
public void testGameSaveLoad() {
Gamer gamer = new Gamer();
History history = new History();
gamer.setLevel(5);
history.add(gamer.save());
gamer.setLevel(10);
gamer.restore(history.get(0));
assertEquals(5, gamer.getLevel());
}
五、总结
备忘录模式通过状态快照与封装隔离机制,为撤销、回滚等场景提供了灵活的解决方案。实现时需注重:
- 角色职责的清晰划分。
- 资源管理策略(如栈结构、序列化)。
- 全覆盖测试用例设计,确保状态一致性与容错性。
该模式广泛应用于编辑器、游戏、数据库等领域,是实现无副作用状态管理的核心工具。