《设计模式-备忘录模式.ppt》由会员分享,可在线阅读,更多相关《设计模式-备忘录模式.ppt(47页珍藏版)》请在三一办公上搜索。
1、Design Patterns,备忘录模式,10103415唐林,大纲,备忘录模式概述备忘录模式的结构与实现备忘录模式的应用实例实现多次撤销备忘录模式的优缺点与适用环境,备忘录模式概述,备忘录模式软件中的“后悔药”撤销(Undo),备忘录模式概述,分析通过使用备忘录模式可以让系统恢复到某一特定的历史状态首先保存软件系统的历史状态,当用户需要取消错误操作并且返回到某个历史状态时,可以取出事先保存的历史状态来覆盖当前状态,备忘录模式概述,备忘录模式的定义对象行为型模式,备忘录模式概述,备忘录模式的定义别名为标记(Token)模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤
2、当前在很多软件所提供的撤销(Undo)操作中就使用了备忘录模式,备忘录模式的结构与实现,备忘录模式的结构,备忘录模式的结构与实现,备忘录模式的结构备忘录模式包含以下3个角色:Originator(原发器)Memento(备忘录)Caretaker(负责人),备忘录模式的结构与实现,备忘录模式的实现典型的原发器类代码:,备忘录模式的结构与实现,备忘录模式的实现典型的备忘录类代码:,备忘录模式的结构与实现,备忘录模式的实现除了Originator类,不允许其他类来调用备忘录类Memento的构造函数与相关方法如果允许其他类调用SetState()等方法,将导致在备忘录中保存的历史状态发生改变,通过
3、撤销操作所恢复的状态就不再是真实的历史状态,备忘录模式也就失去了本身的意义 理想的情况是只允许生成该备忘录的原发器访问备忘录的内部状态,备忘录模式的结构与实现,备忘录模式的实现Java语言实现:将Memento类与Originator类定义在同一个包(package)中来实现封装,使用默认访问标识符来定义Memento类,即保证其在包内可见将备忘录类作为原发器类的内部类,使得只有原发器才可以访问备忘录中的数据,其他对象都无法使用备忘录中的数据,备忘录模式的结构与实现,备忘录模式的实现典型的负责人类代码:,备忘录模式的结构与实现,备忘录模式的实现客户端演示代码:,备忘录模式的应用实例,实例一,备
4、忘录模式的应用实例,实例类图,中国象棋棋子撤销功能结构图,实例代码(1)Chessman:象棋棋子类,充当原发器,实例代码(2)ChessmanMemento:象棋棋子备忘录类,充当备忘录,实例代码(3)MementoCaretaker:象棋棋子备忘录管理类,充当负责人,实例代码(4)Program:客户端测试类,实例代码(5)编译并运行程序,结果如下:,备忘录模式的应用实例,结果及分析通过创建备忘录对象可以将象棋棋子的历史状态信息记录下来,在“悔棋”时取出存储在备忘录中的历史状态信息,用历史状态来覆盖当前状态,从而实现状态的撤销,实现多次撤销,动机有时候用户需要撤销多步操作实现方案:在负责人
5、类中定义一个集合来存储多个备忘录,每个备忘录负责保存一个历史状态,在撤销时可以对备忘录集合进行逆向遍历,回到一个指定的历史状态,还可以对备忘录集合进行正向遍历,实现重做(Redo)或恢复操作,即取消撤销,让对象状态得到恢复,实现多次撤销,结构,改进之后的中国象棋棋子撤销功能结构图,实现多次撤销,修改MementoCaretaker类,实现多次撤销,客户端测试代码,实现多次撤销,客户端测试代码,实现多次撤销,运行结果,实现多次撤销,扩展,本实例只能实现最简单的Undo和Redo操作,并未考虑对象状态在操作过程中出现分支的情况。如果在撤销到某个历史状态之后,用户再修改对象状态,此后执行Undo操作
6、时可能会发生对象状态错误,大家可以思考其产生原因。【注:可将对象状态的改变绘制成一张树状图进行分析。】在实际开发中,可以使用链表或者堆栈来处理有分支的对象状态改变,大家可通过链表或者堆栈对上述实例进行改进。,备忘录模式的应用实例,实例二,备忘录模式的应用实例,备忘录模式的应用实例,备忘录模式的应用实例,备忘录模式的应用实例,备忘录模式的应用实例,保存游戏进度游戏角色、生命力、攻击力、防御力模拟战斗代码,读取游戏进度,备忘录模式的应用实例,class GameRole/生命力 private int vit;public int Vitality get return vit;set vit=v
7、alue;/攻击力 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.de
8、f);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;,不使用备忘录模式的代码,备忘录模式的应用实例,static void Main(string args)/大战Boss前 GameRole lixiaoyao=new GameRole();lixiaoyao.GetInitState();lixiaoyao.StateDisplay();/保
9、存进度 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;li
10、xiaoyao.StateDisplay();Console.Read();,不使用备忘录模式的代码,备忘录模式的应用实例,使用备忘录模式的类图,备忘录模式的应用实例,使用备忘录模式的代码,class GameRole/保存角色状态 public RoleStateMemento SaveState()return(new RoleStateMemento(vit,atk,def);/恢复角色状态 public void RecoveryState(RoleStateMemento memento)this.vit=memento.Vitality;this.atk=memento.Attac
11、k;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 Fig
12、ht()this.vit=0;this.atk=0;this.def=0;,备忘录模式的应用实例,使用备忘录模式的代码,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/攻击力
13、 get return atk;set atk=value;public int Defense/防御力 get return def;set def=value;,备忘录模式的应用实例,使用备忘录模式的代码,/角色状态管理者 class RoleStateCaretaker private RoleStateMemento memento;public void ImportState(RoleStateMemento Record)memento=Record;public RoleStateMemento ExportState()return memento;,备忘录模式的应用实例,使
14、用备忘录模式的代码,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();/恢复之前
15、状态 lixiaoyao.RecoveryState(stateAdmin.ExportState();lixiaoyao.StateDisplay();Console.Read();,备忘录模式的优缺点与适用环境,模式优点提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动,备忘录模式的优缺点与适用环境,模式缺点资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免地需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源,备忘录模式的优缺点与适用环境,模式适用环境保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时能够恢复到先前的状态,实现撤销操作防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象,思考,能否使用原型模式来创建备忘录对象?如果可以,如何实现?,END,Thanks!,