备忘录模式(Memento Pattern):对象状态的快照与恢复
备忘录模式是行为型设计模式的一种,核心思想是在不破坏对象封装性的前提下,捕获对象的内部状态并保存,以便后续将对象恢复到该状态。这种模式就像 “游戏存档”—— 玩家可在关键时刻保存进度,后续可随时加载存档回到之前的状态,核心功能是 “状态的保存与恢复”。
备忘录模式的核心结构

备忘录模式通过三个核心角色实现状态的安全存储与恢复,分工明确且保障封装性:
原发器(Originator)
- 需要被保存状态的对象,负责创建备忘录(记录当前状态)和从备忘录恢复状态。
- 示例:
GameRole(游戏角色,需保存生命值、魔法值等状态)。
备忘录(Memento)
- 存储原发器状态的对象,通常由原发器创建,包含原发器的部分或全部内部状态。
- 备忘录的访问权限严格控制:仅允许原发器读写其状态,其他对象无法修改(保障封装性)。
- 示例:
GameRoleMemento(存储游戏角色的生命值、魔法值)。
管理者(Caretaker)
- 负责管理备忘录的对象,仅存储备忘录但不查看或修改其内容,相当于 “存档管理器”。
- 示例:
GameSaveManager(保存多个游戏存档,提供存档和读档接口)。
代码实现示例
以 “游戏角色状态存档” 为例,展示备忘录模式的实现:游戏角色可保存当前状态(生命值、魔法值),并在需要时恢复。
备忘录(Memento)
1 | // 备忘录:存储游戏角色状态(私有内部类,仅允许原发器访问) |
管理者(Caretaker)
1 | // 管理者:管理游戏存档(备忘录) |
客户端使用
1 | public class MementoDemo { |
输出结果
1 | 当前状态:生命值=100,魔法值=80 |
备忘录模式的核心优势
- 封装性保障
备忘录的状态仅允许原发器访问(如示例中Memento是GameRole的私有内部类),其他对象(如管理者)无法修改,确保状态的安全性。 - 状态快照与恢复
可在任意时刻保存对象状态,需要时快速恢复,适合需要 “回滚” 操作的场景(如游戏存档、事务回滚)。 - 原发器与状态存储分离
原发器无需关心状态如何存储,管理者负责备忘录的管理,符合单一职责原则。
适用场景
- 需要回滚操作的场景
- 游戏存档:保存 / 加载游戏进度。
- 文本编辑器的撤销功能:保存每次编辑前的状态,支持撤销。
- 数据库事务:事务提交前保存状态,失败时回滚。
- 需保存对象部分或全部状态
当对象状态复杂且需频繁保存 / 恢复(如配置项修改、表单填写),备忘录模式可简化状态管理。 - 避免暴露对象内部状态
不希望通过 getter 方法暴露内部状态(破坏封装),可通过备忘录间接保存状态。
优缺点分析
优点
- 高封装性:状态存储与恢复不破坏原发器的封装,内部状态不被外部访问。
- 灵活的状态管理:可保存多个历史状态(如管理者存储备忘录列表),支持多版本恢复。
- 简化原发器职责:原发器无需自行管理状态历史,由管理者统一处理。
缺点
- 资源消耗:若对象状态大或保存频繁,备忘录会占用较多内存(如频繁存档的大型游戏)。
- 状态一致性风险:若原发器状态包含引用类型,备忘录保存的是引用(浅拷贝),可能导致恢复后状态不一致(需深拷贝解决)。
经典应用案例
- 文本编辑器的撤销功能
每次编辑前保存文档状态到备忘录,撤销时从备忘录恢复,如Word的Ctrl+Z。 - 数据库事务管理器
事务执行前保存数据状态,若事务失败,通过备忘录回滚到初始状态。 - 配置中心的版本管理
保存配置项的历史版本(备忘录),支持回滚到之前的配置。 - 状态机的状态回溯
状态机在状态转换时保存历史状态,便于回溯或重新执行。
总结
备忘录模式通过原发器、备忘录和管理者的协作,实现了对象状态的安全保存与恢复,核心是 “封装状态、分离管理”。它特别适合需要回滚操作或状态快照的场景,既能保障对象封装性,又能灵活管理状态历史。使用时需注意平衡状态保存的粒度与资源消耗,避免因频繁保存大对象导致性能问题