一、备忘录(Memento)模式结构
备忘录对象是一个用来存储另外一个对象内部状态的快照(snapshot)的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉住,并外部化,存储起来,从而可以在将来适合的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。
备忘录模式的结构图如下所示
备忘录模式涉及三个角色:备忘录(Memento)角色、发起人(Originator)角色、负责人(Caretaker)角色。
备忘录角色:
(1) 将发起人对象的内部状态存储起来,备忘录可以根据发起人对象的判断来决定存储多少发起人对象的内部状态。
(2) 备忘录可以保护其内容不被发起人对象之外的任何对象所读取。
备忘录有两个等效的接口:
窄接口:负责人(Caretaker)对象和其他除发起人对象之外的任何对象看到的是备忘录的窄接口(narrow interface),这个窄接口只允许它把备忘录对象传给其他对象。
宽接口:与负责人对象看到的窄接口相反的是,发起人对象可以看到一个宽接口(wide interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。
发起人角色:
(1) 创建一个含有当前的内部状态的备忘录对象。(2)使用备忘录对象存储其内部状态。
负责人角色:
(1) 负责保存备忘录对象。(2)不检查备忘录对象的内容。
代码如下:
1 public static void main(String[] args) { 2 3 4 //发起者 5 Originator originator=new Originator(); 6 Caretaker caretaker=new Caretaker(); 7 originator.setState("a"); 8 MementoIF mementoIF=originator.createMemento(); 9 10 caretaker.saveMemento(mementoIF); 11 //改变状态 12 originator.setState("b"); 13 System.out.println("当前state=="+originator.getState()); 14 //恢复状态 15 mementoIF=caretaker.retrieveMemento(); 16 originator.restoreMemento(mementoIF); 17 System.out.println("当前state=="+originator.getState()); 18 } 19 20 } 21 22 23 interface MementoIF{} 24 //发起者 25 class Originator { 26 27 private String state; 28 29 public Originator(){} 30 31 //创建一个备忘录 32 public MementoIF createMemento(){ 33 34 return new Memento(this.state); 35 } 36 //将发起者恢复到备忘录对象记录的状态 37 public void restoreMemento(MementoIF mementoIF){ 38 39 Memento memento=(Memento) mementoIF; 40 41 this.state=memento.getState(); 42 } 43 44 public String getState() { 45 return state; 46 } 47 public void setState(String state) { 48 this.state = state; 49 System.out.println("state="+state); 50 } 51 52 53 //内部类 备忘录 54 class Memento implements MementoIF{ 55 private String state; 56 public Memento(String state){ 57 this.state=state; 58 59 } 60 public String getState() { 61 return state; 62 } 63 public void setState(String state) { 64 this.state = state; 65 } 66 67 } 68 } 69 //备忘录负责人 70 class Caretaker{ 71 72 private MementoIF mementoIF; 73 74 public MementoIF retrieveMemento(){ 75 76 return this.mementoIF; 77 } 78 79 public void saveMemento(MementoIF mementoIF){ 80 81 this.mementoIF=mementoIF; 82 } 83 84 }
执行结果:
state=a
state=b
当前state==b
当前state==a
二、多检查点备忘录
参考:http://www.cnblogs.com/java-my-life/archive/2012/06/06/2534942.html
三、备忘录模式在Java中的应用
J2EE框架中备忘录模式的应用
Java引擎提供Session对象,可以弥补HTTP协议的无状态缺点,存储用户的状态。当一个新的网络用户调用一张JSP网页或者Servlet时,Servlet引擎会创建一个对应于这个用户的Session对象,具体的技术细节可能是向客户端浏览器发送一个含有Session ID的Cookie,或者使用URL改写技术将Session ID 包括在URL中等。在一段有效时间里,同一个浏览器可以反复访问服务器,而Servlet引擎便可以使用这个Session ID来判断来访者应当与哪一个Session对象对应。Session和Cookie的使用都是备忘录模式,如下图所示:
四、备忘录模式的优缺点
优点:
1、 有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取。这时,使用备忘录可以把复杂的发起人内部信息对其他的对象屏弊起来,从而可以恰当地保持封装的边界。
2、 本模式简化了发起人类,发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理它们所需要的这些状态的版本。
3、 当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
缺点:
1、 如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
2、 当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否会昂贵。
参考:
http://blog.csdn.net/fg2006/article/details/6575760
http://men4661273.iteye.com/blog/1633484