自学教程 学编程从这里开始

备忘录模式

《备忘录模式》|设计模式系列第17篇

系列:行为型模式 · 备忘录模式(Memento Pattern)
关键词:快照、保存状态、恢复、原发器、备忘录、负责人

一、什么是备忘录模式

备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

属于行为型设计模式。

简单理解:
备忘录就是对象的状态快照。原发器把当前内部状态打包存入备忘录对象,交给负责人保管;后续需要回滚时,原发器再从备忘录读取状态恢复自身。备忘录对外隐藏数据,只有原发器可以读写快照内容,保证封装不被破坏。
例子:编辑器保存快照,随时撤销回退到之前文本状态。

核心意图
保存对象历史状态,支持回滚;同时保护对象内部状态不对外暴露。

适用场景

  1. 需要保存对象某个时刻状态,支持撤销恢复
  2. 不想直接暴露对象内部字段,破坏封装
  3. 快照数量可控,可维护历史状态列表
  4. 游戏存档、编辑器undo、业务数据回滚

⚠️ 缺点预警:快照对象会占用内存;大量频繁保存状态会造成内存压力;负责人只负责存储,不能修改备忘录内容。

二、UML结构图

角色划分:

  1. Originator(原发器):拥有内部状态,可以创建备忘录,也可以用备忘录恢复状态
  2. Memento(备忘录):存储Originator的内部状态,只允许原发器访问数据
  3. Caretaker(负责人):保存备忘录对象,只负责存储,不能读取/修改备忘录内部数据
  4. Client(客户端):操作原发器和负责人,触发快照保存与恢复

三、Java 完整示例

场景:TextEditor 文本编辑器,保存文本快照,支持恢复。代码全部使用英文。

1. Memento 备忘录

public class Memento {
    private final String content;

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

    public String getContent() {
        return content;
    }
}

2. Originator 原发器

public class TextEditor {
    private String content;

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

    public String getContent() {
        return content;
    }

    // create snapshot
    public Memento save() {
        return new Memento(content);
    }

    // restore from snapshot
    public void restore(Memento memento) {
        this.content = memento.getContent();
    }
}

3. Caretaker 负责人

import java.util.ArrayList;
import java.util.List;

public class Caretaker {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento memento) {
        mementoList.add(memento);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}

4. Client 客户端

public class Client {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        Caretaker caretaker = new Caretaker();

        editor.setContent("Version 1");
        caretaker.add(editor.save());

        editor.setContent("Version 2");
        caretaker.add(editor.save());

        editor.setContent("Version 3");
        System.out.println("Current: " + editor.getContent());

        // restore to version 2
        editor.restore(caretaker.get(1));
        System.out.println("Restore to: " + editor.getContent());
    }
}

运行输出:

Current: Version 3
Restore to: Version 2

四、优缺点总结

✅ 优点

  1. 保存对象快照,方便状态回滚,不破坏封装
  2. 原发器与快照解耦,状态由负责人统一管理
  3. 新增快照逻辑,不修改原有业务代码,符合开闭原则

❌ 缺点

  1. 大量保存备忘录会占用较多内存
  2. Caretaker只负责存储,无法修改备忘录内部状态
  3. 如果对象字段复杂,备忘录复制成本较高

五、备忘录模式 vs 原型模式

模式目标核心
Memento保存历史快照,用于回滚恢复记录对象某一刻状态,交由外部保管
Prototype克隆全新对象,用于复制实例创建对象副本,新对象独立

六、框架源码应用

  • Spring StateMachine 状态快照
  • 各类编辑器/IDE undo 快照机制
  • 数据库事务Savepoint(思想类似)

七、小结

备忘录模式核心:原发器生成状态快照放入备忘录,负责人保管快照,支持对象回滚,保持封装。
注意:不要滥用,如果对象状态很大、快照数量很多,谨慎使用,避免内存溢出。

标签:

0 条笔记