← 返回题目列表

备忘录模式有哪些角色?调用流程是怎样的?

高频 中等 第 7 / 25 题 更新于 2026/07/28
备忘录模式角色调用流程撤销

简化版

备忘录模式有 Originator、Memento、Caretaker 三个角色。流程是 Originator 创建 Memento 保存当前状态,Caretaker 保存 Memento;需要恢复时,Caretaker 把 Memento 交回 Originator,由 Originator 自己恢复状态。

详细版

角色:

  • Originator:原发器,业务对象本身,知道如何保存和恢复状态。
  • Memento:备忘录,封装某一时刻的状态。
  • Caretaker:负责人,管理备忘录历史,如栈、列表、存档记录。

流程:

  1. 用户执行操作前,Originator 创建快照。
  2. Caretaker 保存快照。
  3. 用户继续操作,Originator 状态变化。
  4. 用户触发撤销或恢复。
  5. Caretaker 取出历史快照。
  6. Originator 根据快照恢复状态。

关键原则是:Caretaker 不直接改 Originator 内部字段,也不理解 Memento 细节。

完整版教学

一、Originator 的职责

Originator 是真正拥有状态的对象。比如文本编辑器、游戏角色、配置对象、画布对象。

它最清楚自己的哪些字段需要保存,哪些字段不需要保存。因此创建快照和恢复快照都应该由它自己完成。

二、Memento 的职责

Memento 是状态快照。它可以是不可变对象,保存某一刻的状态值。

好的 Memento 不应该暴露太多可修改接口。否则 Caretaker 可以随意改快照内容,恢复时就可能出现不可预期状态。

三、Caretaker 的职责

Caretaker 像一个快照仓库。它负责保存历史,但不理解快照内部结构。

最常见的数据结构是栈:每次操作前 push 一份快照,撤销时 pop 出最近快照恢复。

如果要支持重做,还需要额外维护 redo 栈。

四、常见误区与工程判断

很多实现会让 Caretaker 直接拿到 Originator 的所有字段,这就退化成外部状态管理,不再是标准备忘录模式。

工程中要明确快照粒度:是每次输入一个字符都保存,还是每次用户完成一次操作保存?粒度太细内存压力大,粒度太粗撤销体验差。

五、三个角色的边界要讲清楚

备忘录模式最重要的不是有几个类,而是三个角色的权限边界。Originator 知道自己的内部状态,也知道如何创建和恢复快照;Memento 保存状态,但不应该把内部细节暴露给外部;Caretaker 只负责保存快照列表或栈,不理解快照里的业务含义。

如果 Caretaker 能直接读写 Memento 的全部字段,模式就失去了封装意义。这样会导致历史管理者越权修改状态,恢复结果不可控。更好的设计是让 Caretaker 只持有 Memento 引用,最多读取时间、说明、版本号等元信息,不碰真正状态。

面试时可以用一句结构化表达:Originator 管“怎么存、怎么恢复”,Memento 管“存下来的状态”,Caretaker 管“什么时候保存、保存多少、恢复哪一个”。把这三句话讲清楚,比背角色定义更像工程回答。

六、用工程约束检验答案

三方协作可用 1 次保存和 1 次恢复说明:Originator 生成快照,Caretaker 压栈;撤销时 Caretaker 弹栈并原样交回 Originator。Memento 不应该反向操纵 Originator,也不负责选择恢复时机。

检查项核心判断工程含义
Originator知道保存哪些状态唯一负责恢复语义
Memento承载快照保持不可变或受限可见
Caretaker管理顺序与容量不依赖快照字段

把关键关系压缩成一条可复述的路径:

save: Originator -> Memento -> Caretaker
undo: Caretaker -> Memento -> Originator
restore: Originator 校验并写回
Caretaker 始终不拆包

回答调用流程时要明确快照是“由原发器创建并由原发器解释”,这是封装成立的关键。

落地前可以再按下面 3 步复核:

  1. 先说明“Originator”的核心机制:知道保存哪些状态;再交代边界:唯一负责恢复语义。
  2. 接着分析“Memento”:承载快照;不能遗漏对应代价或结果:保持不可变或受限可见。
  3. 最后用“Caretaker”检查方案:管理顺序与容量;验收时确认不依赖快照字段。

这三项构成完整判断链:先讲清Originator,再说明Memento,最后用Caretaker检验实现是否越界。

面试中若能给出违反“不依赖快照字段”的反例,再说明修正办法,答案就从模式定义落到了可验证的工程决策。

七、常见误区与追问

  • 误区:只看到“Originator”就认为方案成立。 必须同时说明核心机制“知道保存哪些状态”和工程边界“唯一负责恢复语义”。
  • 误区:把“Memento”当成无条件结论。 只有在“承载快照”成立时,才能据此讨论“保持不可变或受限可见”。
  • 追问:谁决定保存时机? 通常由客户端或 Caretaker 的业务流程决定。
  • 追问:谁决定快照内容? Originator,因为只有它理解恢复所需的内部状态。
  • 追问:Memento 可以是内部类吗? 可以,内部类和可见性控制常用于限制外部访问。
  • 追问:Caretaker 能否持久化快照? 可以,但要额外处理序列化、安全、版本和有效期。
  • 追问:恢复后要删除快照吗? 由撤销策略决定,单次回滚可删,多版本历史也可保留。

八、加强记忆

记忆时抓住这条主线:Originator 拥有状态并创建快照;Memento 封装快照;Caretaker 只管理历史快照;恢复必须交回 Originator 完成。面试回答先给出模式意图,再用调用链或数据流说明角色协作,最后主动交代适用边界与工程代价。