备忘录模式提供一份备份,当以后需要把对象恢复到某状态时会非常方便。
定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样以后就可将该对象状态恢复到原先保存的状态。
通用类图如下:

类图中包含3个角色:
Originator发起人角色负责记录当前时刻状态,定义那些属于备份范围的状态,创建和恢复备忘录数据;
Memento备忘录角色存储Originator发起人对象的内部状态;
Caretaker备忘录管理员角色对备忘录进行保存和提供。
使用场景
- 需要保存和恢复数据的相关状态的场景
- 需要提供可回滚(rollback)的操作时
- 数据库连接的事物管理
注意事项
- 备忘录的生命周期:要注意在备忘录不需要时保证删除
- 备忘录的性能:不要频繁简历备份
扩展
- clone方式的备忘录
备份时通过clone方式保存数据,这种方式融合了发起人角色和备忘录角色,使模式更简洁。不过由于深浅拷贝的约束,clone比较适合于简单/单一的场景。通用类图如下:

- 多状态的备忘录模式
现实中多个状态的对象更为常见。可以通过clone和数据技术(DTO回写到临时表)中实现,下图是另一种方案,使用到了反射技术使得它更为通用。

- 多备份的备忘录模式 有时候需要做多个备份,这时使用检查点(check point)作为备份时的一个戳记,系统级备份通常使用时间戳,然后再管理类使用容器保存数据即可。多备份要注意内存溢出问题,可限定容器上限和数据删除。
- 更好的封装
对于备份的数据,我们要保证它是安全的、没有被篡改的。这时可以使用一个空接口,然后把Memento置为内部类并实现该接口。通用类图如下:

这里用到了双接口设计的方法:提供一个正常业务接口,也叫宽接口,实现必要的业务逻辑,再提供一个空接口,目的是提供给子系统外的模块访问,也叫窄接口,因为窄接口没有任何数据操作,相对比较安全。
参考:
设计模式之禅