【设计模式】行为型-备忘录模式

文章目录


前言

  开发中经常需要撤销、回滚、快照、恢复 功能:比如编辑器 Ctrl+Z、游戏存档、订单回滚、配置恢复。如果直接把对象内部状态暴露出去,会破坏封装;如果自己管理备份,代码又会臃肿。备忘录模式 就是专门解决状态备份与恢复、且不破坏封装的行为型设计模式。


一、概念

  备忘录模式(Memento Pattern) 是一种行为型设计模式 ,核心思想:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后可以将该对象恢复到原先保存的状态。

  简单理解:

  • 原发器(Originator):要备份的对象(如编辑器)
  • 备忘录(Memento):存储状态的快照(不可篡改)
  • 看管人(Caretaker):只负责保存快照,不看内容

一句话总结:
存档 → 快照 → 读档,且快照内容谁都不能改。


二、核心结构

  1. Originator(原发器)
    创建备忘录、从备忘录恢复状态。
  2. Memento(备忘录)
    存储内部状态,只允许原发器读取。
  3. Caretaker(看管人)
    持有备忘录,不能访问/修改内容,只负责存和取。

三、Java 代码实现(编辑器撤销)

场景:编辑器内容备份与恢复(Ctrl+Z)

1. 备忘录(快照)

java 复制代码
// 备忘录:存储状态,不可修改
public class EditorMemento {
    private final String content;

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

    // 只给原发器用
    public String getContent() {
        return content;
    }
}

2. 原发器(编辑器)

java 复制代码
// 原发器:创建快照、恢复快照
public class Editor {
    private String content;

    public void setContent(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    // 创建备忘录(存档)
    public EditorMemento createMemento() {
        return new EditorMemento(content);
    }

    // 从备忘录恢复(读档)
    public void restoreFromMemento(EditorMemento memento) {
        this.content = memento.getContent();
    }
}

3. 看管人(历史记录)

java 复制代码
// 看管人:只保存备忘录,不看内容
public class History {
    private EditorMemento memento;

    public void setMemento(EditorMemento memento) {
        this.memento = memento;
    }

    public EditorMemento getMemento() {
        return memento;
    }
}

4. 客户端测试

java 复制代码
public class Client {
    public static void main(String[] args) {
        Editor editor = new Editor();
        History history = new History();

        // 编辑内容
        editor.setContent("第1版内容");
        // 存档
        history.setMemento(editor.createMemento());

        // 修改
        editor.setContent("第2版修改内容");
        System.out.println("当前:" + editor.getContent());

        // 撤销(恢复)
        editor.restoreFromMemento(history.getMemento());
        System.out.println("撤销后:" + editor.getContent());
    }
}

输出:

复制代码
当前:第2版修改内容
撤销后:第1版内容

四、严格封装(最佳实践)

为了防止外部篡改备忘录,通常做法:

  • Memento 设为私有内部类
  • 只暴露窄接口(空接口)给 Caretaker
  • 只有 Originator 能访问宽接口

这样绝对安全,不会破坏封装。


五、优缺点

优点

  1. 不破坏封装实现备份/恢复
  2. 职责分离:原发器管业务,看管人管存储
  3. 可实现撤销、回滚、快照、重做
  4. 易于实现多版本管理

缺点

  1. 频繁备份会消耗大量内存
  2. 状态复杂时,备忘录管理成本高
  3. 某些语言难以保证备忘录不可篡改

六、应用场景

  • 编辑器撤销(Ctrl+Z)
  • 游戏存档/读档
  • 事务回滚、订单取消
  • 配置恢复、系统快照
  • 虚拟机 checkpoint、容器快照

经典应用:

  • IDEA/Eclipse 撤销重做
  • Git commit(可理解为备忘录)
  • Spring StateMachine 状态保存
  • database transaction rollback

七、备忘录 VS 命令 VS 状态

  • 备忘录:保存/恢复状态
  • 命令:封装行为,支持撤销
  • 状态:状态决定行为

八、总结

  1. 备忘录模式 = 快照 + 存档 + 恢复
  2. 核心:不破坏封装,安全备份状态
  3. 结构:Originator + Memento + Caretaker
  4. 是实现撤销、回滚、存档最标准的设计模式
相关推荐
bryant_meng1 小时前
【Design Patterns】23 Design Patterns: The Ultimate Developer‘s Toolkit
设计模式·编程·计算机科学·设计·工程
狂人开飞机1 小时前
18. 中介者模式(Mediator Pattern)
设计模式·c#·中介者模式
咖啡八杯2 小时前
GoF设计模式——外观模式
java·设计模式·外观模式
江湖中的阿龙3 小时前
23种设计模式
java·开发语言·设计模式
basketball6163 小时前
设计模式入门:7. 策略模式详解 C++实现
c++·设计模式·策略模式
thisiszdy3 小时前
<设计模式> 生产者-消费者模式
设计模式
刀法如飞12 小时前
AI时代:DDD领域驱动建模与Ontology语义建模的区别
java·设计模式·架构
0x3F(小茶)1 天前
嵌入式C设计模式完全指南(基于《C嵌入式编程设计模式》)
c语言·开发语言·单片机·嵌入式硬件·设计模式
basketball6161 天前
设计模式入门:5. 代理模式详解 C++实现
c++·设计模式·代理模式
zzqssliu1 天前
跨境代购系统的物流和通知模块重构思考:从设计模式到生产落地
java·设计模式·重构