一.定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。
二.类图
2.1 常规备忘录
- Originator发起人角色,记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。
- Memento备忘录角色,负责存储Originator发起人对象的内部状态,在恢复的时候提供数据。
- Caretaker备忘录管理员角色:对备忘录进行管理 保存和提供备忘录
2.2 clone方式的备忘录
使用Clone方式的备忘录后,不符合定义中“在该对象之外保存这个状态”这句话,这个方式适用于比较简单的场景或者比较单一的场景中,尽量不要与其他对象产生严重的耦合关系。
2.3 多状态下备忘录模式
- BeanUtils类其中backupProp是把发起人的所有属性值转换到HashMap中,方便备忘录角色存储;restoreProp方法则是把HashMap中的值返回到发起人角色中。不使用Originator对象的拷贝而使用HashMap的原因是为了保证发起人的通用性,在多恢复动作的时候需要对该对象进行多次赋值操作,也容易产生错误。
2.4 强安全性备忘录模式
- 在系统管理上,一个备份的数据是完全、绝对不能修改的,它保证数据的洁净,避免数据污染而使备份失去意义。
- 设计领域中,把备忘录的阅读权限保证只能是发起人可读就成了,使用内置类可以做到这一点。
- IMemento是一个空接口。
- 没有绝对的安全,可以使用refelect反射修改Memento的数据
三.使用场景
- 需要保存和恢复数据的相关状态场景。
- 提供一个可回滚的操作;比如Word中CTRL+Z组合键等
- 需要监控的副本场景中。例如要监控一个对象的属性,但是监控又不应该作为系统的主业务来调用,它只是边缘应用,既是出现监控不准,错误报警也影响不大,因此一般的做法是备份一个主线程中的对象,然后由分析程序类分析。
- 数据库连接的事务管理就是用的备忘录模式。
四.注意事项
- 备忘录的生命期。备忘录创建出来就要在“最近“的代码中使用,要主动管理它的生命周期,建立就要使用,不使用就要立刻删除其引用,等待垃圾回收器对它的回收处理。
- 备忘录性能。不要在频繁尽力备份的场景中使用备忘录模式,比如一个for循环中,一是因为控制不了备忘录建立的对象数量,而是大对象建立是要消耗资源的,会影响系统的性能。
- 如果要设计一个在运行期决定备份状态的框架,则建议采用AOP框架来实现,避免采用动态代理无谓地增加程序的逻辑性。