Design Patterns
备忘录模式
刘 伟 (Sunny)\rweiliu_china@126.com
大纲
\r
备忘录模式概述\r备忘录模式的结构与实现\r备忘录模式的应用实例\r实现多次撤销\r备忘录模式的优缺点与适用环境\r
备忘录模式概述
备忘录模式——软件中的“后悔药”——撤销(Undo)
备忘录模式概述
分析\r通过使用备忘录模式可以让系统恢复到某一特定的历史状态\r首先保存软件系统的历史状态,当用户需要取消错误操作并且返回到某个历史状态时,可以取出事先保存的历史状态来覆盖当前状态\r
备忘录模式概述
备忘录模式的定义\r\r\r\r\r\r对象行为型模式
备忘录模式概述
备忘录模式的定义\r别名为标记(Token)模式\r提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤\r当前在很多软件所提供的撤销(Undo)操作中就使用了备忘录模式
备忘录模式的结构与实现
备忘录模式的结构\r\r
备忘录模式的结构与实现
备忘录模式的结构\r备忘录模式包含以下3个角色:\rOriginator(原发器)\rMemento(备忘录)\rCaretaker(负责人)
备忘录模式的结构与实现
备忘录模式的实现\r典型的原发器类代码:
备忘录模式的结构与实现
备忘录模式的实现\r典型的备忘录类代码:
备忘录模式的结构与实现
备忘录模式的实现\r除了Originator类,不允许其他类来调用备忘录类Memento的构造函数与相关方法\r如果允许其他类调用SetState()等方法,将导致在备忘录中保存的历史状态发生改变,通过撤销操作所恢复的状态就不再是真实的历史状态,备忘录模式也就失去了本身的意义 ?\r理想的情况是只允许生成该备忘录的原发器访问备忘录的内部状态
备忘录模式的结构与实现
备忘录模式的实现\rC#语言实现:\r将Memento类与Originator类定义在同一个程序集(Assembly)中来实现封装,使用访问标识符internal来定义Memento类,即保证其在程序集内可见\r将备忘录类作为原发器类的内部类,使得只有原发器才可以访问备忘录中的数据,其他对象都无法使用备忘录中的数据
备忘录模式的结构与实现
备忘录模式的实现\r典型的负责人类代码:
备忘录模式的结构与实现
备忘录模式的实现\r客户端演示代码:
备忘录模式的应用实例
实例说明
备忘录模式的应用实例
实例类图
中国象棋棋子撤销功能结构图
备忘录模式的应用实例
实例代码\r(1) Chessman:象棋棋子类,充当原发器\r(2) ChessmanMemento:象棋棋子备忘录类,充当备忘录\r(3) MementoCaretaker:象棋棋子备忘录管理类,充当负责人\r(4) Program:客户端测试类
演示……
参考代码 (DesignPattern\MementoSample)
备忘录模式的应用实例
结果及分析\r通过创建备忘录对象可以将象棋棋子的历史状态信息记录下来,在“悔棋”时取出存储在备忘录中的历史状态信息,用历史状态来覆盖当前状态,从而实现状态的撤销\r\r\r\r
实现多次撤销
动机\r有时候用户需要撤销多步操作\r实现方案:在负责人类中定义一个集合来存储多个备忘录,每个备忘录负责保存一个历史状态,在撤销时可以对备忘录集合进行逆向遍历,回到一个指定的历史状态,还可以对备忘录集合进行正向遍历,实现重做(Redo)或恢复操作,即取消撤销,让对象状态得到恢复\r\r\r
实现多次撤销
结构\r\r\r\r\r
改进之后的中国象棋棋子撤销功能结构图
实现多次撤销
实现\r\r\r\r\r
实现多次撤销
实现\r\r\r\r\r
演示……
参考代码 (DesignPattern\MementoExtend)
备忘录模式的优缺点与适用环境
模式优点\r提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤\r实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动
备忘录模式的优缺点与适用环境
模式缺点\r资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免地需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源\r\r
备忘录模式的优缺点与适用环境
模式适用环境\r保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时能够恢复到先前的状态,实现撤销操作\r防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象\r
思考
能否使用原型模式来创建备忘录对象?如果可以,如何实现?
END
Thanks!