← 返回题目列表

备忘录模式和命令模式在撤销场景中有什么区别?

高频 困难 第 13 / 25 题 更新于 2026/07/28
备忘录模式命令模式撤销模式对比

简化版

备忘录模式通过保存状态快照来撤销,命令模式通过把操作封装成命令并提供反向操作来撤销。备忘录适合状态快照容易保存的场景,命令适合操作可逆、需要记录行为日志、队列执行的场景,两者也可以结合使用。

详细版

备忘录模式:

  • 保存对象状态。
  • 撤销时恢复旧状态。
  • 不一定关心具体执行了什么操作。
  • 快照大时内存成本高。

命令模式:

  • 保存操作对象。
  • 撤销时执行反向操作或回滚逻辑。
  • 适合日志、排队、宏命令、重放。
  • 反向操作复杂时实现困难。

结合方式:

  • 命令执行前保存备忘录。
  • 命令负责执行和撤销入口。
  • 备忘录负责恢复状态。

完整版教学

一、备忘录撤销的是状态

备忘录模式不关心你是通过什么操作到达当前状态的。它只保存“之前是什么样”。

撤销时直接把状态恢复回去。这适合状态规模可控、快照容易保存的场景,比如表单草稿、配置对象、画布状态。

二、命令模式撤销的是操作

命令模式更关注动作。每个命令知道自己做了什么,也知道如何撤销。

比如“向右移动 10 像素”的撤销操作是“向左移动 10 像素”。这种方式不一定要保存完整对象状态,内存更省。

但如果操作不可逆,比如随机生成、复杂合并、外部系统调用,反向命令就难写。

三、两者可以结合

在复杂系统中,命令对象可以保存一个备忘录。执行命令前保存状态,撤销命令时恢复状态。

这样命令模式负责行为组织,备忘录模式负责状态恢复。

四、常见误区与工程判断

面试中不要简单说“它们都能撤销”。要讲清撤销依据不同:一个靠快照,一个靠反向操作。

工程选择时看成本:状态小、恢复简单,用备忘录;操作可逆、需要日志和重放,用命令;两者都需要时可以组合。

五、撤销方案里两种模式经常配合使用

命令模式和备忘录模式都能支持撤销,但思路不同。命令模式关注“把操作封装起来”,撤销时通常执行一个反向操作;备忘录模式关注“把状态保存下来”,撤销时恢复历史快照。前者偏行为日志,后者偏状态快照。

如果一个操作很容易反向执行,比如加 10 可以减 10,插入一段文本可以删除这段文本,命令模式比较自然。如果对象状态复杂、反向操作难写或者容易遗漏副作用,保存备忘录会更稳。比如画布对象、表单对象、游戏角色状态,直接恢复快照往往比推导反向动作可靠。

真实项目里经常组合:每个 Command 执行前让 Originator 创建 Memento,命令执行失败或撤销时恢复快照。这样命令负责表达“用户做了什么”,备忘录负责保证“能回到哪里”。面试时说出这种组合,会比单纯比较二者更有深度。

还有一个判断角度是副作用。如果操作会调用外部系统、发送消息、写日志,单纯恢复对象快照并不能撤销外部副作用;这时命令模式的操作日志、补偿动作和事务边界更重要。备忘录负责对象状态,不负责让世界倒流。

六、用工程约束检验答案

备忘录记录“操作前状态”,命令记录“如何执行与反执行”。移动坐标从 10 到 15 时,Memento 可保存 10;Command 可保存增量 +5,并在 undo 时执行 -5。前者恢复直接,后者更依赖逆操作正确性。

检查项核心判断工程含义
Memento恢复状态快照适合逆操作难描述
Command执行/撤销请求适合动作可逆且需日志化
组合Command 持有执行前 Memento复杂命令也能可靠回滚

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

command.execute 前 createMemento
执行具体业务动作
undo 时取出该快照
Originator.restore 恢复

选择依据不是都能 undo,而是系统更容易可靠保存状态,还是可靠表达逆操作。

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

  1. 先说明“Memento”的核心机制:恢复状态快照;再交代边界:适合逆操作难描述。
  2. 接着分析“Command”:执行/撤销请求;不能遗漏对应代价或结果:适合动作可逆且需日志化。
  3. 最后用“组合”检查方案:Command 持有执行前 Memento;验收时确认复杂命令也能可靠回滚。

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

面试中若能给出违反“复杂命令也能可靠回滚”的反例,再说明修正办法,答案就从模式定义落到了可验证的工程决策。

七、常见误区与追问

  • 误区:只看到“Memento”就认为方案成立。 必须同时说明核心机制“恢复状态快照”和工程边界“适合逆操作难描述”。
  • 误区:把“Command”当成无条件结论。 只有在“执行/撤销请求”成立时,才能据此讨论“适合动作可逆且需日志化”。
  • 追问:命令撤销一定用逆命令吗? 不一定,也可让命令保存 Memento 并恢复。
  • 追问:备忘录知道执行了什么吗? 通常不知道,它只表达某时刻的状态。
  • 追问:哪种更节省空间? 增量命令常较小,但取决于参数和恢复需求,不能一概而论。
  • 追问:外部副作用如何撤销? 快照不能自动撤回邮件或支付,必须设计补偿动作和幂等。
  • 追问:两者组合的代价是什么? 命令对象和快照都要管理生命周期,历史结构更复杂。

八、加强记忆

记忆时抓住这条主线:备忘录靠状态快照撤销;命令靠反向操作撤销;快照大时备忘录成本高;两者可以组合实现复杂撤销。面试回答先给出模式意图,再用调用链或数据流说明角色协作,最后主动交代适用边界与工程代价。