Memento 备忘录模式.doc_第1页
Memento 备忘录模式.doc_第2页
Memento 备忘录模式.doc_第3页
Memento 备忘录模式.doc_第4页
Memento 备忘录模式.doc_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Menmento (备忘录)模式一、应用场景:1二、备忘录(memento) 模式概念:21、定义22、模式的结构及涉及角色:2备忘录 (Memento)角色3发起人(Originator)角色3负责人 (Caretaker)角色33、备忘录模式的宽接口和白箱实现34、备忘录模式的双重接口45、备忘录模式的黑箱实现66、负责人角色的增强77、备忘录模式与多重检查点78、备忘录模式的变种自述历史模式89、备忘录模式的变种“假如”协议模式810、备忘录模式与其他模式关系911、备忘录模式的应用10JDBC与数据库10J2EE框架中备忘录模式的应用10浏览器的Cookie文件10系统配置文件10三、代码示例:111、范例一:白箱实现112、范例二:黑箱实现133、范例三:多重检查点164、范例四:自述历史模式20四、备忘录模式优缺点:221。优点:222。缺点:22一、应用场景:在玩一些通关游戏中,如果我们在某一关失败将只能从头再来,怎样保证我们尽量少的从头再来呢?我们使用word、eclipse中可以使用“撤销”、“重做”可以撤销刚才的操作而恢复操作前的内容,这是为什么呢?它的原理是什么呢?这将是我们这一次介绍的模式的应用。二、备忘录(memento) 模式概念:1、定义Memento模式(memento pattern)又叫做snapshot pattern(快照模式)或 Token(标记),是对象的行为模式。 Memento模式是用一个memento对象来存储另外一个对象的内部状态(前提条件是不破坏封装),将一个对象的状态捕捉住,并外部化存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。 Memento对象是一个用来存储另外一个对象内部状态的快照的对象。 需要存储多个状态时,这些状态常常是一个对象历史发展的不同阶段的快照,存储这些快照的备忘录对象叫做此对象的历史;某一个快照所处的位置叫做检查点(Check Point) 。2、模式的结构及涉及角色:备忘录模式简略类图如下:使用增强的负责人角色的备忘录模式类图: 具体区分将在后边6、负责人角色的增强 中描述。备忘录模式涉及三个角色:备忘录 (Memento)角色、发起人(Originator)角色和负责人 (Caretaker)角色。 备忘录 (Memento)角色1)Memento ,名词,英文解释为:纪念物,纪念品;引起回忆的东西。2)主要负责工作如下:1 存储发起人(Originator)对象的内部状态;2 发起人(Originator)根据需要决定备忘录角色存储发起人的哪些内部状态。,备忘录可以保护其内容不被发起人以外的其他对象访问。 3)Memento可以有下列两种类接口(API):l 窄接口(narrow interface)窄接口是给外部负责人(caretaker)对象(和其他除发起人对象之外的任何对象)看到的,负责人角色对于备忘录角色中存放的属性是不可见的。窄接口不会泄露memento对象的内部状态。l 宽接口(wide interface)与狭义接口相反,宽接口是给发起人(Originator)对象看的,允许它读取所有的数据,是一个可读取对象状态恢复原状时的必要信息的所有方法的集合。宽接口会泄露memento对象的内部状态。视情况使用两种不同接口可以避免对象封装性遭破坏。 发起人(Originator)角色 Originator,名词,英文解释为:创建人,发起人;起因,来源;源发站。 主要负责工作如下:1 创建一个含有当前的内容状态的备忘录对象。2 使用备忘录对象存储其内部状态。 负责人 (Caretaker)角色Caretaker,名词,英文解释为:照顾者,管理人,看管人;主要负责工作如下:1 负责保存备忘录对象。2 不对备忘录的内容进行操作或检查。3、备忘录模式的宽接口和白箱实现 1白箱实现的概念:备忘录角色对所有对象都提供一个接口,即宽接口,备忘录对象的内部所存储的状态就对所有对象公开。这种实现叫做“白箱实现”。 “白箱”实现将发起人角色的状态存储在一个大家都看得到的打分,是破坏封装性的。可以通过程序员的自律,一定程度上保持封装性。备忘录模式的“白箱”实现又叫做“白箱”备忘录模式。2“白箱”备忘录模式的实现 参看 三、代码示例 2、范例一 3白箱实现的优缺点: 优点:简单。 缺点:破坏发起人状态的封装。4、备忘录模式的双重接口 1.双重接口: 为了“不破坏封装”,备忘录对象提供双重接口,即对发起人对象提供宽接口,对其他对象提供窄接口,减少外部代码直接利用公共接口修改对象的潜在危险。 2.java中双重接口设计方案: 设计:定义宽接口类wide、窄接口类narrow,实现类concreteClass实现2个接口类,User对象可以调用wide接口,Other类调用narrow类,设计思路如下图: 可以简化如下图: 分析:如图所示,这样就实现的宽接口、窄接口的设计。但是,这样就能阻止除了User对象以外的所有其他对象引用宽接口吗?不能。其他对象仍然可以引用concreteClass中的宽接口。继续改进一: 改进一:将concreteClass类定义为User的内部成员类,如图:分析:虽然已经是内部类,但是仍然不仅对User类存在,而且对所有的同一package中的类都存在,因为成员类并没有私有访问权限。没有达到目的,继续改进二。改进二:不仅将concreteClass类定义为User的内部成员类,而且concreteClass类的所有方法都设计为私有的。如图:User类实现代码格式如下:public class User /*实现窄接口,内部类*/class ConcreteClass implements Narrow private void operation1() System.out.println(operation1); private void operation2() System.out.println(operation2); 5、备忘录模式的黑箱实现 1.黑箱实现的类图: 根据4、备忘录模式的双重接口 内容介绍,我们可以发现,使用内部类实现备忘录模式能够实现“不破坏封装”的目的,下图就是备忘录模式的“黑箱”实现简略类图:2“黑箱”备忘录模式的实现 参看 三、代码示例 2、范例二 3黑箱实现的优缺点: 优点:不破坏发起人状态的封装。6、负责人角色的增强前边的实现中,负责人角色只负责备忘录对象的存储、恢复,具体备忘录的创建、发起人的状态恢复等都在客户端(main)中直接调用发起人角色和备忘录角色完成的。如果让负责人角色调用备忘录角色和发起人角色,进行备忘录的创建和赶紧备忘录恢复发起人状态,那么客户端便步再需要协调各备忘录角色和发起人角色,而只需要调用负责人角色即可。如下图所示,具有增强功能的负责人角色可以引用发起人角色进行操控。具体实现将与7.备忘录模式与多重检查点的范例一起展示。7、备忘录模式与多重检查点1.多重检查点: 以上白箱实现、黑箱实现部分的示例实现都是只存储一个状态,也可以叫只有一个检查点,实际软件中可能需要存储多个状态,或者叫做有多个检查点。 备忘录模式可以将发起人对象的状态存储到备忘录对象里,可以将发起人对象恢复到备忘录对象所存储的某一个检查点上。下图例为有多重检查点的模式实现: 2备忘录模式的多重检查点实现 参看 三、代码示例 2、范例三 3多重检查点的优缺点: 优点:不破坏发起人状态的封装。8、备忘录模式的变种自述历史模式1自述历史模式: 发起人兼顾负责人角色,自己管理自己的状态,同时备忘录对象做为发起人类的内部类,各个方法私有,保证了发起人角色自己可以存取备忘录状态,而外部对象则不可以。类图如下: 2范例实现 参看 三、代码示例 2、范例四 3多重检查点的优缺点: 优点:没有独立的负责人角色,每一个发起人兼顾负责人角色,简单易懂。 缺点:如果有独立的负责人角色,如果有多个发起人角色,可以共享同一个负责人角色,或在多态性前提下使用多个负责人子类型,但自述历史模式无法做到代码共享。9、备忘录模式的变种“假如”协议模式 (这部分了解下就可以,暂时没有找到相应代码。) 1备忘录模式的操作过程: 第1步:客户端为发起人角色创建一个备忘录对象; 第2步:调用发起人对象的某个操作,此操作可以撤销; 第3步:检查发起人对象所处状态的有效性。 检查方式可以是发起人对象的内部自查,也可以由外部对象进行检查; 第4步:如果需要,将发起人操作撤销,根据备忘录对象记录将发起人状态恢复过来。 2“假如”协议操作过程: 第1步:将发起人做一个拷贝; 第2步:在拷贝上执行每个操作; 第3步:检查这个拷贝的状态是否有效和自恰; 第4步:如果检查结果是无效或不自恰,扔掉这个拷贝并触发异常处理程序;相反,则在原对象 执行这个操作。 对与撤销一个操作并恢复操作前状态较为复杂和困难的发起人对象来说,是一个较为谨慎和有效的做法。3“假如”协议优缺点: 优点:保证发起人对象永远不会处于无效或不自恰状态。 缺点:1。成功的操作必须执行两次。2。如果在拷贝和原对象均有共享数据,修改原对象或拷贝对象都会导致数据被修改。 10、备忘录模式与其他模式关系Memento模式常常与命令(Command)模式和迭代子(Iterator)模式一同使用。1命令(Command)模式:命令模式把一个请求或操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求牌堆或记录请求日志,可以提供命令的撤销和恢复功能。备忘录模式可以结合命令模式来实作Redo/Undo的功能,将操作前后的物件状态记录下来,并记录所使用的命令,当要实现Undo/Redo时,只要取回Memento物件以复原物件状态即可。命令模式常常需要维护一个历史清单聚集,并使用迭代子模式便历历史清单的元素,命令模式需要这一功能来实现命令的撤销和恢复。2迭代子(Iterator)模式:迭代子模式:又叫游标(cursor)模式。迭代子模式可以顺利的访问一个聚集中的元素而不必暴露聚集的内部表象。Java聚集:vector、ArrayList 、HashMap等。 迭代子对象在迭代过程中会存储迭代的状态,包含游标的位置等,这是备忘录模式的应用。 当备忘录支持多个检查单时,在各个检查点之间进行遍历需要使用迭代子模式。11、备忘录模式的应用 JDBC与数据库商业逻辑与存储逻辑分割开来。原因如下:1.。开发商业逻辑与开发数据库技能完全不同,分割开可以由不同设计师操作,便于系统维护。2.。商业逻辑变化时,存储方案不一定变化。例如:系统升级。3存储逻辑变化,商业逻辑不一定变化。例如:移库。 J2EE框架中备忘录模式的应用1Java Servlet引擎使用session对象。2用户输入数据。 浏览器的Cookie文件 系统配置文件例如:浏览器样式自定义。三、代码示例:1、范例一:白箱实现Caretaker是用来保留原发者所创造的备忘录物件,以供日后复原时取回,state表示一个内部状态,内部状态多时,也可以将之组织为一个类别,Caretaker维护的Memento可以是多个,用来实现Redo与Undo多次的功能。1. Originator.java:package mementoPattern.demo1;public class Originator private String state; public String getState() return state;public void setState(String state) this.state = state; /*构造函数*/ public Originator(String state) this.state = state; /*返回一个新的备忘录对象*/public Memento createMemento() return new Memento(state); /* * 将发起人恢复到备忘录对象所记载的状态 */ public void restoreMemento(Memento memento) this.state = memento.getState(); 2. Memento.java:package mementoPattern.demo1;public class Memento private String state; public Memento(String state) this.state = state;public String getState() return this.state;3. Caretaker.java:package mementoPattern.demo1;public class Caretaker private Memento memento; public void setMemento(Memento memento) this.memento = memento; public Memento getMemento() return memento; 4. main.java:package mementoPattern.demo1;public class Main public static void main(String args) Originator originator = new Originator(on); Caretaker caretaker = new Caretaker(); /做备份caretaker.setMemento(originator.createMemento(); /输出System.out.println(新建并备份后Originator状态值:+originator.getState(); / some operations make the objects state changed originator.setState(off); /输出System.out.println(修改Originator后状态值:+originator.getState(); / 恢复操作 originator.restoreMemento(caretaker.getMemento(); /输出System.out.println(恢复Originator备份状态值后:+originator.getState(); 执行结果: 新建并备份后Originator状态值:on修改Originator后状态值:off恢复Originator备份状态值后:on2、范例二:黑箱实现1MementoIF.java (窄接口定义类):package mementoPattern.demo2;/*memento 窄接口*/public interface MementoIF 2Originator.java(发起人类,含内部类Memento,各方法私有,实现MementoIF):package mementoPattern.demo2;import mementoPattern.demo1.Memento;public class Originator private String state;public String getState() return this.state;public void setState(String state) this.state = state;System.out.println(state=+state);/* 构造函数 */public Originator() /* 构造函数 */public Originator(String state) this.state = state;/* 返回一个新的备忘录对象 */public MementoIF createMemento() return new Memento(this.state);/* * 将发起人恢复到备忘录对象所记录的状态 */public void restoreMemento(MementoIF memento) /实现接口Memento am=(Memento)memento;/赋值this.state = am.getSavedState();/*内部成员类,备忘录*/protected class Memento implements MementoIFprivate String savedState;/*构造子类*/private Memento(String someState)savedState=someState;/*状态的赋值方法*/public void setSavedState(String someState) savedState = someState;/*获取状态值*/Public String getSavedState() return savedState;3Caretaker.java(负责人类):package mementoPattern.demo2;public class Caretaker private MementoIF memento;/*保存备忘录*/public void saveMemento(MementoIF memento) this.memento = memento; /*返回备忘录*/public MementoIF retriveMemento() return this.memento; 4Main.java(客户端类):package mementoPattern.demo2;public class Main /* * param args */public static void main(String args) Originator originator = new Originator(on); Caretaker caretaker = new Caretaker(); /创建备忘录,并将发起人对象状态存储起来caretaker.saveMemento(originator.createMemento(); /输出System.out.println(新建并备份后Originator状态值:+originator.getState(); / 修改状态 originator.setState(off); /输出System.out.println(修改Originator后状态值:+originator.getState(); / 恢复操作 originator.restoreMemento(caretaker.retriveMemento(); /输出System.out.println(恢复Originator备份状态值后:+originator.getState(); 执行结果如下:新建并备份后Originator状态值:onstate=off修改Originator后状态值:off恢复Originator备份状态值后:on3、范例三:多重检查点1MementoIF.java (窄接口定义类):package mementoPattern.demo2;/*memento 窄接口*/public interface MementoIF 2Originator.java(发起人类):package mementoPattern.demo3;import java.util.Enumeration;import java.util.Vector;public class Originator private Vector states;private int index;/* 构造函数 */public Originator() states=new Vector();index=0;/* 返回一个新的备忘录对象 */public Memento createMemento() return new Memento(states,index);/* * 将发起人恢复到备忘录对象所记录的状态 */public void restoreMemento(Memento memento) /实现接口states=memento.getState();index = memento.getIndex();/* * 状态的赋值 * param state */public void setState(String state) this.states.addElement(state) ;index+;/* * 打印所有状态 */public void printStates()System.out.println(Total number of states:+index);for(Enumeration e=states.elements();e.hasMoreElements();)System.out.println(e.nextElement();3Memento.java(备忘录类):package mementoPattern.demo3;import java.util.Vector;public class Memento implements MementoIF private Vector states;private int index;/*构造子类*/public Memento(Vector states,int index)/*克隆vector对象,将克隆存入到备忘录对象内部 不这样,将会造成客户端和备忘录对象持有对同一个vector对象的引用, 也可以同时修改这个vector对象,会造成系统崩溃 */this.states=(Vector)states.clone();this.index=index;/*获取状态值*/public Vector getState() return states;public int getIndex() return index;4Caretaker.java(负责人类):package mementoPattern.demo3;import java.util.Vector;public class Caretaker private Originator origin;private Vector mementos=new Vector();private int current;/* * 构造函数 * param ont */public Caretaker(Originator ont)this.origin=ont;current=0;/* * 创建一个新检查点 */public int createMemento()Memento mem=origin.createMemento();mementos.addElement(mem);return current+;/*将发起人恢复到某个检查点*/public void retriveMemento(int index) Memento mem=(Memento) mementos.elementAt(index) ;origin.restoreMemento(mem);/*将某个检查点删除*/public void removeMemento(int index) mementos.removeElementAt(index) ;5Main.java(客户端类):package mementoPattern.demo3;public class Main /* * param args */public static void main(String args) Originator og = new Originator(); Caretaker ct = new Caretaker(og); /改变状态og.setState(state 0);/建立一个检查点ct.createMemento();/改变状态og.setState(state 1);/建立一个检查点ct.createMemento();/改变状态og.setState(state 2);/建立一个检查点ct.createMemento();/改变状态og.setState(state 3);/建立一个检查点ct.createMemento();/改变状态og.setState(state 4);/建立一个检查点ct.createMemento();/打印出所有的检查点og.printStates();/恢复到第2个检查点System.out.println(Restoring to 2);ct.retriveMemento(2);og.printStates();/恢复到第0个检查点System.out.println(Restoring to 0);ct.retriveMemento(0);og.printStates();/恢复到第3个检查点System.out.println(Restoring to 3);ct.retriveMemento(3);og.printStates();4、范例四:自述历史模式1MementoIF.java (窄接口定义类):package mementoPattern.demo2;/*memento 窄接口*/public interface MementoIF 2Originator.java(发起人类):package mementoPattern.demo4;import mementoPattern.demo1.Memento;public class Originator private String state;/*改变状态*/public void changeStatus(String nstate)this.state=nstate;System.out.println(state has been changed to:+state);/* 构造函数 */public Originator() /* 返回一个新的备忘录对象 */public M

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论