Java设计模式之行为型模式(备忘录模式)实现方式与测试用例

最近看到一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

一、实现方式

  1. 基础结构与角色定义
    备忘录模式包含三个核心角色,协作关系如下:
  • Originator(发起人):需保存/恢复状态的对象,提供创建和恢复备忘录的方法。
  • Memento(备忘录):存储发起人状态的载体,通常设计为不可变类。
  • Caretaker(管理者):管理备忘录对象,不操作其内容。
    代码示例(文本编辑器场景):
java 复制代码
// 发起人:文本编辑器
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); }
}
  1. 高级实现技巧
  • 多级撤销与重做:使用栈结构管理备忘录。

    java 复制代码
    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); }
    }
  • 资源优化:通过序列化持久化备忘录。

    java 复制代码
    // 发起人支持序列化
    public class SerializableOriginator extends Originator implements Serializable {
        private String state;
    }

二、测试用例设计

  1. 基础功能验证
    目标:验证状态保存与恢复的正确性。
java 复制代码
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());
    }
}
  1. 异常场景测试
    目标:验证空备忘录或非法操作的容错性。
java 复制代码
@Test(expected = IllegalStateException.class)
public void testRestoreNullMemento() {
    Editor editor = new Editor();
    editor.restore(null);  // 触发异常
}
  1. 多级撤销测试
    目标:验证栈结构管理的撤销/重做功能。
java 复制代码
@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());
}
  1. 性能与资源测试
    目标:监控内存占用与优化策略有效性。
java 复制代码
@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);
}

三、关键设计原则

  1. 封装性保护:
    • Memento类仅对Originator开放宽接口,其他类仅通过Caretaker管理。
  2. 职责分离:
    • 状态管理由Caretaker负责,状态逻辑由Originator实现。
  3. 资源控制:
    • 限制备忘录数量(如仅保存最近10个状态)或使用增量存储。

四、实际应用示例

场景:游戏存档系统

java 复制代码
// 发起人:游戏角色
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());
}

五、总结

备忘录模式通过状态快照与封装隔离机制,为撤销、回滚等场景提供了灵活的解决方案。实现时需注重:

  1. 角色职责的清晰划分。
  2. 资源管理策略(如栈结构、序列化)。
  3. 全覆盖测试用例设计,确保状态一致性与容错性。
    该模式广泛应用于编辑器、游戏、数据库等领域,是实现无副作用状态管理的核心工具。