java23种设计模式-备忘录模式

发布于:2025-02-28 ⋅ 阅读:(103) ⋅ 点赞:(0)

备忘录模式(Memento Pattern)学习笔记


编程相关书籍分享:https://blog.csdn.net/weixin_47763579/article/details/145855793
DeepSeek使用技巧pdf资料分享:https://blog.csdn.net/weixin_47763579/article/details/145884039


1. 模式定义

行为型设计模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便后续恢复对象到原先保存的状态。

2. 适用场景

✅ 需要实现撤销/重做功能
✅ 需要保存对象历史快照
✅ 需要提供系统状态回滚机制
✅ 需要隔离对象状态存储细节
✅ 需要实现事务回滚操作

3. 模式结构

creates
Originator
-state: String
+createMemento() : Memento
+restore(m: Memento)
Memento
-state: String
+getState()
+setState()
Caretaker
-mementos: List
+addMemento(m: Memento)
+getMemento(index: int) : Memento

4. 核心角色

角色 说明
Originator 原发器:需要保存状态的对象
Memento 备忘录:存储原发器内部状态的对象(通常不可修改)
Caretaker 管理者:负责保存/恢复备忘录,但不能操作备忘录内容

5. 代码示例

5.1 文本编辑器撤销功能

// 备忘录类  
final class TextMemento {  
    private final String content;  

    public TextMemento(String content) {  
        this.content = content;  
    }  

    public String getContent() {  
        return content;  
    }  
}  

// 原发器类  
class TextEditor {  
    private StringBuilder content = new StringBuilder();  

    public void append(String text) {  
        content.append(text);  
    }  

    public TextMemento save() {  
        return new TextMemento(content.toString());  
    }  

    public void restore(TextMemento memento) {  
        content = new StringBuilder(memento.getContent());  
    }  

    public void print() {  
        System.out.println("当前内容: " + content);  
    }  
}  

// 管理者类  
class HistoryManager {  
    private final Stack<TextMemento> history = new Stack<>();  

    public void push(TextMemento memento) {  
        history.push(memento);  
    }  

    public TextMemento pop() {  
        return history.pop();  
    }  
}  

// 客户端  
public class Client {  
    public static void main(String[] args) {  
        TextEditor editor = new TextEditor();  
        HistoryManager history = new HistoryManager();  

        editor.append("Hello");  
        history.push(editor.save());  
        editor.print();  

        editor.append(" World");  
        history.push(editor.save());  
        editor.print();  

        System.out.println("执行撤销操作:");  
        editor.restore(history.pop());  
        editor.print();  
    }  
}  
/* 输出:  
当前内容: Hello  
当前内容: Hello World  
执行撤销操作:  
当前内容: Hello */  

6. 模式变种

6.1 白箱 vs 黑箱实现

类型 实现方式 特点
白箱 Memento公开状态访问方法 违反封装原则,但实现简单
黑箱 Memento使用内部类隐藏实现 保持封装性,Java常用实现方式
// 黑箱实现示例  
class Originator {  
    private String state;  

    public IMemento save() {  
        return new Memento(state);  
    }  

    public void restore(IMemento m) {  
        this.state = ((Memento)m).getState();  
    }  

    // 内部类实现备忘录  
    private static class Memento implements IMemento {  
        private final String state;  

        private Memento(String state) {  
            this.state = state;  
        }  

        private String getState() {  
            return state;  
        }  
    }  
}  

interface IMemento {} // 标记接口  

7. 优缺点分析

✔️ 优点

  • 保持对象封装边界
  • 简化原发器职责
  • 支持状态历史管理
  • 实现撤销/恢复机制

缺点

  • 消耗内存资源(需保存多个状态副本)
  • 频繁保存影响性能
  • 需要合理设计备忘录存储策略
  • 增加系统复杂度

8. 相关模式对比

模式 目的 关键区别
原型模式 对象克隆 关注对象复制,备忘录关注状态保存
命令模式 操作封装 命令模式可存储操作,备忘录存储状态
状态模式 状态管理 状态模式改变行为,备忘录保存状态

9. 实际应用案例

  • 文本/图形编辑器的撤销栈
  • 数据库事务回滚机制
  • 游戏存档/读档功能
  • 浏览器页面历史记录
  • IDE的本地历史功能
  • 金融系统的交易快照
  • Java序列化机制(Serializable)

10. 最佳实践建议

  1. 控制备忘录数量
// 使用最大历史记录限制  
class BoundedHistory {  
    private final Deque<Memento> stack = new ArrayDeque<>();  
    private final int maxSize;  

    public BoundedHistory(int maxSize) {  
        this.maxSize = maxSize;  
    }  

    public void push(Memento m) {  
        if (stack.size() >= maxSize) {  
            stack.removeFirst();  
        }  
        stack.addLast(m);  
    }  
}  
  1. 增量存储优化
// 仅存储变化量  
class DeltaMemento {  
    private final String delta;  
    private final long timestamp;  
    // ...  
}  
  1. 使用序列化实现深存储
// 通过序列化保存对象状态  
class SerializedMemento {  
    public static byte[] serialize(Object obj) throws IOException {  
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();  
             ObjectOutputStream oos = new ObjectOutputStream(bos)) {  
            oos.writeObject(obj);  
            return bos.toByteArray();  
        }  
    }  

    public static Object deserialize(byte[] data) throws Exception {  
        try (ByteArrayInputStream bis = new ByteArrayInputStream(data);  
             ObjectInputStream ois = new ObjectInputStream(bis)) {  
            return ois.readObject();  
        }  
    }  
}  
  1. 结合原型模式
class Originator implements Cloneable {  
    public Memento save() {  
        return new Memento(this.clone());  
    }  

    protected Originator clone() {  
        try {  
            return (Originator) super.clone();  
        } catch (CloneNotSupportedException e) {  
            throw new AssertionError();  
        }  
    }  
}  

🕰️ 设计原则体现

  1. 单一职责原则:状态管理职责分离到备忘录
  2. 开闭原则:新增备忘录类型无需修改原发器
  3. 封装性:保护对象内部状态不被直接访问

通过备忘录模式,可以实现灵活的状态管理机制,特别适合需要支持撤销/重做、事务回滚等功能的场景。该模式在编辑器、游戏开发、金融系统中应用广泛,是保护对象状态完整性的经典解决方案。