论文2012 — 2013学年第 2 学期论文题目备忘录模式学生姓名学号专业班级指导教师2013 年7 月 1 日备忘录模式1.备忘录模式概述对象的状态依赖于它的变量的取值情况,对象在程序运行期间的各个时刻可能具有不同的状态。
在某些应用中,程序可能需要使用一种合理的方式来保存对象在某一时刻的状态,以便在需要时,对象能恢复原先保存的状态。
在备忘录模式中,称需要保存状态的对象为“原发者”,称负责保存原发者可以访问备忘录中的细节,即可以访问备忘录中的数据,以便恢复原发者的状态,而负责人只能保存和得到备忘录,但访问备忘录中的数据收到一定的限制。
备忘录模式使原发者可以将自己的状态暴露内部数据的同时,又保证了数据的封装性。
另外,经过精心设计的备忘录通过保存原发者状态中最本质的数据,就能使原发者根据此备忘录中的数据恢复原始状态。
2.备忘录模式的定义备忘录模式是关于怎样保存对象状态的成熟模式,其关键是提供一个备忘录对象,该备忘录负责存储一个对象的状态,程序可以在磁盘或内存中保存这个备忘录,这样以后就可将该对象恢复到原先保存的状态。
3. 备忘录模式的结构和使用3.1备忘录模式包括三种角色:原发者(Originator):需要在某个时刻保存其状态的对象。
原发者负责创建备忘录,比如使用createMemento()方法创建一个备忘录,然后原发者该备忘录记录自己的状态。
当原发者需要恢复某个时刻的状态是,它通过获得相应的备忘录中的数据来恢复那个时刻的状态,比如原发者调用restoreFromMemento(Memento mem)方法,并通过参数men制定的备忘录恢复状态。
备忘录(Memento):负责存储原发者状态的对象,创建备忘录的类和创建原发者的类在同一个包中,该类提供的访问数据的方法都是友好方法,是的只有和原发者在同一个包中的类的实例才可以访问备忘录中的数据。
负责人(Caretaker):负责管理保存备忘录的对象。
负责人如果不和原发者在同一个包中,就不能对备忘录中的内容进行修改或读取。
如果需要将备忘录保存到磁盘,负责人可以使用对象流将备忘录写入文件。
3.2备忘录模式的UML类图备忘录模式的类图如图所示,备忘录模式中原发者角色,Recoder 类的实例是备忘录(Menmento)角色,SaveRecoder类的实例是负责人(Caretaker)角色。
3.3使用内部类创建备忘录备忘录模式是原发者可以将自己的状态暴露给备忘录,但其他对象想要获得备忘录中的数据会受到一定的限制,这就保证了原发者暴露内部数据的同时又保证了数据的封装性。
在java语言中,如果负责人不打算使用对象流来保存备忘录,而是仅仅将备忘录暂时存放在内存中,那么就可以使用内部类来创建备忘录面积将创建备忘录的类作为原发者(Originator)的内部类,这样一来,仅仅原发者才可以访问备忘录中的数据,其他对象都无法访问备忘录中的数据。
4. 备忘录模式的优点(1)备忘录模式使用备忘录可以把原发者的内部状态保存起来,使只有恨“亲密的”的对象可以访问备忘录中数据。
(2)备忘录模式强调了类设计单一责任原则,即将状态的刻画和保存分开。
5. 适合使用备忘录模式的情景下列情况很适合使用备忘录模式:1.对象状态的备忘足以使对象可以完全恢复到原来的状态。
2.使用一个直接的接口来取得状态会使实现细节过程化,这样会打破对象的封装性。
6. 备忘录模式在Java中的应用以下通过一个简单的问题来描述怎样使用备忘录模式。
这个简单的问题是让用户从一个文本文件phrase.txt中挑选自己喜欢的成语,并将挑选出的成语保存得到另一个文件favorPhrase.txt中。
Phrase.txt 的每一行是一个成语,应用程序中有一个对象负责按顺序读取phrase.txt中的成语,并将读取的成语作为的备选成语,即程序将询问用户是否将该成语保存到favorPhrase.txt。
由于phrase.txt的内容很多,用户使用改程序一段时间后,可能退出该程序,但希望下次启动该程序时,能从上一次使用该程序时所提供的最后一个备选成语之后继续挑选自己喜欢的成语1.原发者(Originator)本问题中原发者(Originator)是ReadPhrase类的实例,ReadPhrase 类色实例负责按行读取名字phrase.txt的文本,该文件的每一行是一个成语,例如phrase.txt文件的前两行:刻舟求剑安步当车ReadQuestion类的包名是tom.jiafei,因此ReadPhrase类编译后得到的字节码文件需要保存到tom/jiafei目录中。
ReadQuestion类代码如下ReadPhrase,javapackage tom.jiafei;import java.io.*;public class ReadPhrase {long readPosition; File file;RandomAccessFile in; String phrase=null;public ReadPhrase(File file){this.file=file;try{in=new RandomAccessFile(file,"r");}catch(IOException exp){ }}public Memento createMemento(){Memento mem=new Memento();mem.setPositionState(readPosition);return mem;}public void restoreFromMemento(Memento mem){readPosition=mem.getPositionState();}public String readLine(){try{ in.seek(readPosition);phrase=in.readLine();if(phrase!=null){byte b[]= phrase.getBytes("iso-8859-1");phrase=new String(b);}readPosition=in.getFilePointer();}catch(IOException exp){}return phrase;}public void closeRead(){try{ in.close();}catch(IOException exp){ }}}2.备忘录(Memento):备忘录(Memento)和ReadPhrase类的包名相同,因此Memento 类编译后得到的字节码文件需要保存到tom/jiafei目录中。
这样一来,只有和ReadPhrase类在同一包中的类的实例可以访问备忘录中的数据,否则无法获得备忘录中的数据。
Memento类的代码如下:Memento.javapackage tom.jiafei;public class Memento implements java.io.Serializable{private long state;void setPositionState(long state){this.state=state;}long getPositionState(){return state;}}3.负责人(Caretaker):对于本问题,负责人(Caretaker)是Caretaker类,该类没有包名,负责人负责管理备忘录,因此,需使用import语句引入Memento 类。
为了编译Caretaker类,可以将tom/jiafei作为Caretaker类所在目录的子目录。
Caretaker类的代码如下:Caretaker.javaimport tom.jiafei.*;import java.io.*;public class Caretaker{File file;private Memento memento=null;Caretaker(){file=new File("saveObject.txt");}public Memento getMemento(){if(file.exists()) {try{FileInputStream in=new FileInputStream("saveObject.txt");ObjectInputStream inObject=new ObjectInputStream(in);memento=(Memento)inObject.readObject();}catch(Exception exp){}}return memento;}public void saveMemento(Memento memento){try{ FileOutputStream out=new FileOutputStream("saveObject.txt");ObjectOutputStream outObject=new ObjectOutputStream(out);outObject.writeObject(memento);}catch(Exception exp){}}}7. 综合应用举例打rpg游戏的时候经常在打大boss之前把游戏保存一下,如果死了,就重新来。
其实这就是备忘录模式。
看代码:view plaincopy to clipboardprint?package designpattern.memento.game;public class GameRole {private int vitality;private int attack;private int defense;public GameRole(){this.vitality = 100;this.attack = 100;this.defense = 100;public void showState(){System.out.println("vitality = " + vitality + "\nattack = " + attack + "\ndefence = " + defense);}public RoleStateMemo save(){return new RoleStateMemo(vitality, attack, defense);}public void recover(RoleStateMemo m){System.out.println("太菜了我,还好我存盘了,哈哈。