备忘录模式(Memento)撤销机制:实现对象变量状态的回滚功能
作者:小宇宙叶知秋
时间:2026-05-21
浏览:0
备忘录模式通过“状态快照”与“隔离恢复”实现撤销功能。发起人生成并恢复状态快照,备忘录封装不可变状态,管理者仅负责存储。该模式强调状态完整性与封装性,确保回滚时所有关联变量一致恢复,对外提供简洁接口。
说到撤销功能,很多开发者第一反应可能是全局历史栈或者反射。但备忘录模式(Memento)提供了一种更优雅、更内聚的思路:它的核心,其实是“状态快照”加上“隔离恢复”。简单来说,就是让对象自己掌握状态的存档与读档,外部只负责保管存档文件,无权插手内容。

发起人(Originator)必须亲自管理状态生命周期
状态是对象的私有财产,如果允许外部直接读写,封装性就荡然无存了。因此,发起人对象需要对外提供两个清晰的方法:
- sa veToMemento():在状态变更前调用。关键在于,这个方法内部必须执行深拷贝——无论是用Python的
copy.deepcopy、Ja va中构造一个全新的对象,还是Go里显式复制切片和map——生成一份只读的状态快照。 - restoreFromMemento(memento):这个方法只做一件事:从传入的备忘录中提取值,并安全地赋值给自己的内部字段。整个过程不暴露字段名,也不允许外部对备忘录内容做任何修改。
备忘录(Memento)要真正“不可变”且“不可见”
备忘录不是一个简单的数据容器,它更像一个上了锁的保险箱,里面封存着某一时刻的状态:
- 字段全部私有化:在Ja va或C#里用
private final;在Go里用小写字母开头的未导出字段;在Python中,虽然靠约定,但结合深拷贝能有效保障。 - 对外提供安全的访问:通常只提供一个
getState()类方法,而且返回值最好是不可变类型(如String、ImmutableList)或其副本,防止外部拿到引用后意外篡改快照。 - 构造权限收紧:备忘录的构造函数应该只对发起人开放。这可以通过Ja va的包访问权限、C++的friend声明或Go的同包可见性来实现,确保管理者无法私自创建或篡改备忘录。
管理者(Caretaker)只做“存取中转”,不碰状态语义
管理者的角色极其纯粹,它就像一个带编号的仓库管理员:
- 用一个数组、列表或栈来保存多个备忘录,以此支持多步撤销。
- 提供
push(memento)和pop()或get(index)这样的存取方法。但请注意,它绝不应该去调用备忘录的getState()方法。 - 它的职责仅限于存储和提供,不校验状态逻辑,不合并快照,也不做序列化——所有业务相关的逻辑,都应该牢牢锁在发起人对象内部。
回滚时注意变量粒度与一致性
撤销操作最怕的就是状态不一致。一次完整的回滚,必须还原所有关联变量,不能只改一半:
- 举个例子,文本编辑器撤销时,如果只恢复了文本内容却忘了光标位置,用户体验就会很割裂。同样,游戏角色恢复状态时,不能只回满血量却漏掉了技能冷却时间。
- 一个实用的建议是:将逻辑上强关联的变量打包进同一个备忘录。比如
EditorMemento(content, cursorPos, selection)。 - 另外,如果变量之间存在计算依赖(比如总价=单价×数量),应该在发起人内部保存原始的、独立的字段,而不是保存计算后的衍生值。这样恢复时才能保证基础逻辑的正确性。
总而言之,备忘录模式通过清晰的职责划分——发起人负责生成和解析状态,备忘录负责封装不可变快照,管理者负责单纯存储——实现了既安全又灵活的状态回滚机制。它把变化的可能性留在了对象内部,对外则提供了简洁稳定的接口,这正是优秀封装设计的体现。
作者最新文章
极度公式
2026-09-16 17:43
索尼WH-1000XM4C发布:复刻经典折叠设计并升级现代接口
2026-09-08 19:10
PDF转TXT操作步骤与转换后内容核对指南
2026-09-04 18:03
Photoshop安装失败或启动异常:系统要求、安装流程与故障排查指南
2026-09-03 06:04
PDF文件体积过大如何压缩及压缩后清晰度检查方法
2026-09-02 19:30
热门文章
更多
精品专题
更多
Mac软件
更多
WINDOWS
更多


































