资源预览内容
第1页 / 共47页
第2页 / 共47页
第3页 / 共47页
第4页 / 共47页
第5页 / 共47页
第6页 / 共47页
第7页 / 共47页
第8页 / 共47页
第9页 / 共47页
第10页 / 共47页
亲,该文档总共47页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
www.ChinaSA.infoDDesign esign P Patternsatterns备忘录模式备忘录模式备忘录模式备忘录模式10103415唐林唐林www.ChinaSA.info大纲w备忘录模式概述w备忘录模式的结构与实现w备忘录模式的应用实例w实现多次撤销w备忘录模式的优缺点与适用环境www.ChinaSA.info备忘录模式概述w备忘录模式软件中的“后悔药”撤销(Undo)www.ChinaSA.info备忘录模式概述w分析通过使用备忘录模式可以通过使用备忘录模式可以让系统让系统恢复到某一特定的历史状态恢复到某一特定的历史状态首先首先保存软件系统的历史状态保存软件系统的历史状态,当用户需要取消错误操作并且返当用户需要取消错误操作并且返回到某个历史状态时,可以回到某个历史状态时,可以取出取出事先保存的历史状态来覆盖当前事先保存的历史状态来覆盖当前状态状态www.ChinaSA.info备忘录模式概述w备忘录模式的定义对象行为型对象行为型模式模式备忘忘录模模式式:在在不不破破坏坏封封装装的的前前提提下下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可可以以在在以以后后将将对象恢复到原先保存的状象恢复到原先保存的状态。Memento Pattern: Without violating encapsulation,captureandexternalizeanobjectsinternalstatesothatthe object can be restored to this state later.www.ChinaSA.info备忘录模式概述w备忘录模式的定义别名为别名为标记标记(Token)模式模式提供了一种提供了一种状态恢复状态恢复的实现机制,使得用户可以方便的实现机制,使得用户可以方便地地回到一个特定的历史步骤回到一个特定的历史步骤当前在很多软件所提供的当前在很多软件所提供的撤销撤销(Undo)操作操作中就使用了中就使用了备忘录模式备忘录模式www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的结构www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的结构备忘录模式包含以下备忘录模式包含以下3个角色:个角色:Originator(原发器)Memento(备忘录)Caretaker(负责人)www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的实现典型的原发器类代码:典型的原发器类代码:namespaceMementoSamplepublicclassOriginatorprivatestringstate;publicOriginator(stringstate)this.state=state;/ 创建一个建一个备忘忘录对象象 internal Memento CreateMemento() return new Memento(this); / 根据根据备忘忘录对象恢复原象恢复原发器状器状态 internal void RestoreMemento(Memento m) state = m.GetState(); publicvoidSetState(stringstate)this.state=state;publicstringGetState()returnthis.state;www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的实现典型的备忘录类代码:典型的备忘录类代码:namespaceMementoSample /备忘忘录类,默,默认可可见性性,在在程序程序集内可集内可见 internal class Mementoprivatestringstate; internal Memento(Originator o) state = o.GetState(); internalvoidSetState(stringstate)this.state=state;internalstringGetState()returnthis.state;www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的实现除了除了Originator类,类,不允许其他类来调用备忘录类不允许其他类来调用备忘录类Memento的构造函数与相关方法的构造函数与相关方法如果允许其他类调用如果允许其他类调用SetState()等方法,将导致在备等方法,将导致在备忘录中保存的历史状态发生改变,通过撤销操作所恢忘录中保存的历史状态发生改变,通过撤销操作所恢复的状态就不再是真实的历史状态复的状态就不再是真实的历史状态,备忘录模式也就,备忘录模式也就失去了本身的意义失去了本身的意义 理想的情况是理想的情况是只允许生成该备忘录的原发器访问备忘只允许生成该备忘录的原发器访问备忘录的内部状态录的内部状态www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的实现Java语言实现:语言实现:将Memento类与Originator类定义在同一个包(package)中来实现封装,使用默认访问标识符来定义Memento类,即保证其在包内可见将备忘录类作为原发器类的内部类,使得只有原发器才可以访问备忘录中的数据,其他对象都无法使用备忘录中的数据www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的实现典型的负责人类代码:典型的负责人类代码:namespaceMementoSamplepublicclassCaretakerprivateMementomemento; internal Memento GetMemento() return memento; internal void SetMemento(Memento memento) this.memento = memento; www.ChinaSA.info备忘录模式的结构与实现w备忘录模式的实现客户端演示代码:客户端演示代码:classClientpublicstaticvoidmain(Stringargs) /创建原建原发器器对象象 Originator ori = new Originator(状状态(1);Console.WriteLine(ori.GetState();/创建建负责人人对象,保存象,保存创建的建的备忘忘录对象象 Caretaker ct = new Caretaker(); ct.SetMemento(ori.CreateMemento(); ori.SetState(状状态(2);Console.WriteLine(ori.GetState();/从从负责人人对象中取出象中取出备忘忘录对象,象,实现撤撤销 ori.RestoreMemento(ct.GetMemento();Console.WriteLine(ori.GetState();Console.Read();OnOffOnwww.ChinaSA.info备忘录模式的应用实例w实例一某软件公司欲开发一款可以运行在Android平台的触摸式中国象棋软件,由于考虑到有些用户是“菜鸟”,经常不小心走错棋;还有些用户因为不习惯使用手指在手机屏幕上拖动棋子,常常出现操作失误,因此该中国象棋软件要提供“悔棋”功能,用户走错棋或操作失误后可恢复到前一个步骤。如下图所示:中国象棋中国象棋软件界面示意件界面示意图为了实现“悔棋”功能,现使用备忘录模式来设计该中国象棋软件。www.ChinaSA.info备忘录模式的应用实例w实例类图中国象棋棋子撤销功能结构图中国象棋棋子撤销功能结构图www.ChinaSA.infow实例代码(1) Chessman:象棋棋子类,充当原发器:象棋棋子类,充当原发器www.ChinaSA.infow实例代码(2) ChessmanMemento:象棋棋子备忘录类,充当备忘录:象棋棋子备忘录类,充当备忘录www.ChinaSA.infow实例代码(3) MementoCaretaker:象棋棋子备忘录管理类,充当负责人:象棋棋子备忘录管理类,充当负责人www.ChinaSA.infow实例代码(4) Program:客户端测试类:客户端测试类www.ChinaSA.infow实例代码(5) 编译并运行程序,结果如下:编译并运行程序,结果如下:www.ChinaSA.info备忘录模式的应用实例w结果及分析通过创建备忘录对象可以通过创建备忘录对象可以将象棋棋子的历史状态信息将象棋棋子的历史状态信息记录下来记录下来,在,在“悔棋悔棋”时取出存储在备忘录中的历史时取出存储在备忘录中的历史状态信息,状态信息,用历史状态来覆盖当前状态用历史状态来覆盖当前状态,从而实现状,从而实现状态的撤销态的撤销www.ChinaSA.info实现多次撤销w动机有时候用户需要有时候用户需要撤销多步操作撤销多步操作实现方案:实现方案:在负责人类中在负责人类中定义一个集合定义一个集合来存储多个备来存储多个备忘录,每个备忘录负责保存一个历史状态,忘录,每个备忘录负责保存一个历史状态,在撤销时在撤销时可以对备忘录集合进行逆向遍历,回到一个指定的历可以对备忘录集合进行逆向遍历,回到一个指定的历史状态史状态,还可以,还可以对备忘录集合进行正向遍历,实现重对备忘录集合进行正向遍历,实现重做做(Redo)或恢复操作或恢复操作,即取消撤销,让对象状态得到,即取消撤销,让对象状态得到恢复恢复www.ChinaSA.info实现多次撤销w结构改进之后的中国象棋棋子撤销功能结构图改进之后的中国象棋棋子撤销功能结构图www.ChinaSA.info实现多次撤销w修改MementoCaretaker类www.ChinaSA.info实现多次撤销w客户端测试代码www.ChinaSA.info实现多次撤销w客户端测试代码www.ChinaSA.info实现多次撤销w运行结果www.ChinaSA.info实现多次撤销w扩展 本实例只能实现最简单的本实例只能实现最简单的Undo和和Redo操作,并未操作,并未考虑对象状态在操作过程中出现分支的情况。如果在撤销考虑对象状态在操作过程中出现分支的情况。如果在撤销到某个历史状态之后,用户再修改对象状态,此后执行到某个历史状态之后,用户再修改对象状态,此后执行Undo操作时可能会发生对象状态错误,大家可以思考其操作时可能会发生对象状态错误,大家可以思考其产生原因。产生原因。【注:可将对象状态的改变绘制成一张树状图注:可将对象状态的改变绘制成一张树状图进行分析。进行分析。】 在实际开发中,可以使用链表或者堆栈来处理有分支在实际开发中,可以使用链表或者堆栈来处理有分支的对象状态改变,大家可通过链表或者堆栈对上述实例进的对象状态改变,大家可通过链表或者堆栈对上述实例进行改进。行改进。www.ChinaSA.info备忘录模式的应用实例w实例二www.ChinaSA.info备忘录模式的应用实例www.ChinaSA.info备忘录模式的应用实例www.ChinaSA.info备忘录模式的应用实例www.ChinaSA.info备忘录模式的应用实例www.ChinaSA.info备忘录模式的应用实例w保存游戏进度游戏角色、生命力、攻击力、防御力游戏角色、生命力、攻击力、防御力模拟战斗代码,读取游戏进度模拟战斗代码,读取游戏进度www.ChinaSA.info备忘录模式的应用实例 class GameRole /生命力 private int vit; public int Vitality get return vit; set vit = value; /攻击力 private int atk; public int Attack get return atk; set atk = value; /防御力 private int def; public int Defense get return def; set def = value; /状态显示 public void StateDisplay() Console.WriteLine(角色当前状态:); Console.WriteLine(体力:0, this.vit); Console.WriteLine(攻击力:0, this.atk); Console.WriteLine(防御力:0, this.def); Console.WriteLine(); /获得初始状态 public void GetInitState() this.vit = 100; this.atk = 100; this.def = 100; /战斗 public void Fight() this.vit = 0; this.atk = 0; this.def = 0; w不使用备忘录模式的代码www.ChinaSA.info备忘录模式的应用实例 static void Main(string args) /大战Boss前 GameRole lixiaoyao = new GameRole(); lixiaoyao.GetInitState(); lixiaoyao.StateDisplay(); /保存进度 GameRole backup = new GameRole(); backup.Vitality = lixiaoyao.Vitality; backup.Attack = lixiaoyao.Attack; backup.Defense = lixiaoyao.Defense; /大战Boss时,损耗严重 lixiaoyao.Fight(); lixiaoyao.StateDisplay(); /恢复之前状态 lixiaoyao.Vitality = backup.Vitality; lixiaoyao.Attack = backup.Attack; lixiaoyao.Defense = backup.Defense; lixiaoyao.StateDisplay(); Console.Read(); w不使用备忘录模式的代码www.ChinaSA.info备忘录模式的应用实例w使用备忘录模式的类图www.ChinaSA.info备忘录模式的应用实例w使用备忘录模式的代码 class GameRole /保存角色状态 public RoleStateMemento SaveState() return (new RoleStateMemento(vit, atk, def); /恢复角色状态 public void RecoveryState(RoleStateMemento memento) this.vit = memento.Vitality; this.atk = memento.Attack; this.def = memento.Defense; /状态显示 public void StateDisplay() Console.WriteLine(角色当前状态:); Console.WriteLine(体力:0, this.vit); Console.WriteLine(攻击力:0, this.atk); Console.WriteLine(防御力:0, this.def); Console.WriteLine(); /获得初始状态 public void GetInitState() this.vit = 100; this.atk = 100; this.def = 100; /战斗 public void Fight() this.vit = 0; this.atk = 0; this.def = 0; www.ChinaSA.info备忘录模式的应用实例w使用备忘录模式的代码 class RoleStateMemento /角色状态存储箱 private int vit; private int atk; private int def; public RoleStateMemento(int vit, int atk, int def) this.vit = vit; this.atk = atk; this.def = def; public int Vitality /生命力 get return vit; set vit = value; public int Attack /攻击力 get return atk; set atk = value; public int Defense /防御力 get return def; set def = value; www.ChinaSA.info备忘录模式的应用实例w使用备忘录模式的代码 /角色状态管理者 class RoleStateCaretaker private RoleStateMemento memento; public void ImportState(RoleStateMemento Record) memento = Record; public RoleStateMemento ExportState() return memento; www.ChinaSA.info备忘录模式的应用实例w使用备忘录模式的代码 static void Main(string args) /大战Boss前 GameRole lixiaoyao = new GameRole(); lixiaoyao.GetInitState(); lixiaoyao.StateDisplay(); /保存进度 RoleStateCaretaker stateAdmin = new RoleStateCaretaker(); stateAdmin.ImportState(lixiaoyao.SaveState(); /大战Boss时,损耗严重 lixiaoyao.Fight(); lixiaoyao.StateDisplay(); /恢复之前状态 lixiaoyao.RecoveryState(stateAdmin.ExportState(); lixiaoyao.StateDisplay(); Console.Read(); www.ChinaSA.info备忘录模式的优缺点与适用环境w模式优点提供了一种状态恢复的实现机制提供了一种状态恢复的实现机制,使,使得用户可以方便地回到一个特定的历得用户可以方便地回到一个特定的历史步骤史步骤实现了对信息的封装实现了对信息的封装,一个备忘录对,一个备忘录对象是一种原发器对象状态的表示,不象是一种原发器对象状态的表示,不会被其他代码所改动会被其他代码所改动www.ChinaSA.info备忘录模式的优缺点与适用环境w模式缺点资源消耗过大资源消耗过大,如果需要保存的原发器,如果需要保存的原发器类的成员变量太多,就不可避免地需要类的成员变量太多,就不可避免地需要占用大量的存储空间,占用大量的存储空间,每保存一次对象每保存一次对象的状态都需要消耗一定的系统资源的状态都需要消耗一定的系统资源www.ChinaSA.info备忘录模式的优缺点与适用环境w模式适用环境保存一个对象在某一个时刻的全部状态保存一个对象在某一个时刻的全部状态或部分状态或部分状态,这样以后,这样以后需要时能够恢复需要时能够恢复到先前的状态到先前的状态,实现撤销操作实现撤销操作防止外界对象破坏一个对象历史状态的防止外界对象破坏一个对象历史状态的封装性封装性,避免将对象历史状态的实现细,避免将对象历史状态的实现细节暴露给外界对象节暴露给外界对象www.ChinaSA.info思考w能否使用原型模式来创建备忘录对象?如果可以,如何实现?www.ChinaSA.infoENDEND
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号