商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 备忘录模式(Memento)撤销机制:实现对象变量状态的回滚功能

备忘录模式(Memento)撤销机制:实现对象变量状态的回滚功能

  发布于2026-05-21 阅读(0)

扫一扫,手机访问

说到撤销功能,很多开发者第一反应可能是全局历史栈或者反射。但备忘录模式(Memento)提供了一种更优雅、更内聚的思路:它的核心,其实是“状态快照”加上“隔离恢复”。简单来说,就是让对象自己掌握状态的存档与读档,外部只负责保管存档文件,无权插手内容。

备忘录模式(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)
  • 另外,如果变量之间存在计算依赖(比如总价=单价×数量),应该在发起人内部保存原始的、独立的字段,而不是保存计算后的衍生值。这样恢复时才能保证基础逻辑的正确性。

总而言之,备忘录模式通过清晰的职责划分——发起人负责生成和解析状态,备忘录负责封装不可变快照,管理者负责单纯存储——实现了既安全又灵活的状态回滚机制。它把变化的可能性留在了对象内部,对外则提供了简洁稳定的接口,这正是优秀封装设计的体现。

本文转载于:https://www.php.cn/faq/2450923.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注