Memento模式

一、Memento模式的目的:

memento是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原先保存的状态.

二、Memento模式的简单例子:

下面的例子来源于Jdon网站的《GoF设计模式系列》的《Memento模式》,虽然简单却形象地表明了Memento模式的应用

 

 

Java代码  收藏代码
  1. package memento;  
  2.   
  3. import java.io.File;  
  4.   
  5. public class Originator {  
  6.       
  7.     private int number;   
  8.     private File file = null;  
  9.       
  10.     public Originator(){  
  11.           
  12.     }  
  13.       
  14.     // 创建一个Memento,将自身作为参数传入  
  15.     public Memento getMemento(){  
  16.         return new Memento(this);  
  17.     }  
  18.       
  19.     //从Memento中取出保存的数据,恢复为原始状态  
  20.     public void setMemento(Memento m){  
  21.         number = m.getNumber();  
  22.         file = m.getFile();  
  23.     }  
  24.   
  25.     public int getNumber() {  
  26.         return number;  
  27.     }  
  28.   
  29.     public void setNumber(int number) {  
  30.         this.number = number;  
  31.     }  
  32.   
  33.     public File getFile() {  
  34.         return file;  
  35.     }  
  36.   
  37.     public void setFile(File file) {  
  38.         this.file = file;  
  39.     }     
  40. }  

 

 

 

Java代码  收藏代码
  1. package memento;  
  2.   
  3. import java.io.File;  
  4. import java.io.Serializable;  
  5.   
  6. public class Memento implements Serializable {  
  7.       
  8.     private int number;  
  9.     private File file = null;  
  10.       
  11.     public Memento(Originator o){  
  12.         this.number = o.getNumber();  
  13.         this.file = o.getFile();  
  14.     }  
  15.   
  16.     public int getNumber() {  
  17.         return this.number;  
  18.     }  
  19.   
  20.     public void setNumber(int number) {  
  21.         this.number = number;  
  22.     }  
  23.   
  24.     public File getFile() {  
  25.         return this.file;  
  26.     }  
  27.   
  28.     public void setFile(File file) {  
  29.         this.file = file;  
  30.     }  
  31.       
  32.       
  33. }  

 

 

三、Memento模式的特点:

在需要提供保存、恢复对象状态的类中,必须提供两个方法:

.保存对象当前状态方法:将对象自身(this)作为参数传入,创建备忘录。
.恢复对象之前状态的方法:取出备忘录/接收一个备忘录对象,从中获取对象之前的状态

模式的缺点是耗费大,如果内部状态很多,再保存一份,无意要浪费大量内存.

注意:Memento模式保存的是操作前对象的状态,而不是操作后对象的状态;否则就没办法做恢复了

 

 

 

一、“Mementor”模式和“堆栈”的结合-“GUI界面撤销功能”的实现

·当用户在面板中拖动一个组件到编辑区时,应用程序为编辑区创建一个备忘录,并把它加入到一个堆栈中(注意此时备忘录中包含的是操作前的状态,而非操作后的状态)

·当用户单击“撤销”按钮时,应用程序就将堆栈顶部的备忘录弹出,然后将编辑区恢复为该备忘录所记录的状态

当可视化应用程序启动后,首先向空的堆栈中压入一个初始的空备忘录,并且保证绝对不会将该备忘录从栈中弹出,从而确保该栈的顶部总是有一个有效的备忘录。当栈中仅包含一个备忘录的时候,应用程序应当禁用“撤销”按钮

 

二、“Mementor”模式和“Observer”模式的结合-“通知式恢复”

在某些情况下,我们希望为GUI组件注册一些监听器,当组件的状态发生改变时,可以通知所有对它感兴趣的监听器,这种情况我们可以用“Observer”模式来实现。

还是以我们上面的例子来说:假如用户从面板中拖动一个组件到编辑区后,有几个监听器对它感兴趣,并且采取了相应的操作,现在用户单击了“撤销”按钮,那么我们应该把这个事件通知所有监听器,告诉他们必须恢复之前所有的状态。这种情况就可以把两种模式结合起来使用:

·当对象被创建时,激活并为该对象注册监听器(观察着),监听器创建一个初始化备忘录,保存编辑区的原始信息
·当对象(被观察着)被销毁(用户单击“撤销”按钮时),向所有注册的监听器发送信息
·监听器(观察者)接收到信息,从备忘录中取出编辑区信息的备忘录,恢复当前编辑区的状态

 

三、“Mementor”模式和“Observer”模式、“责任链”模式的结合-“链式通知恢复”

在上面我们提到了将“Mementor”模式和“Observer”模式结合起来达到到“通知式恢复”的效果,考虑下面一个情况:

如果我们在安装一个软件或执行一个长时间、多次交互的情况,加入用户在最后一个操作中选择了“取消”操作,我们应该怎么做呢?

我的想法是在为每一次操作创建一个备忘录,并将其放在“责任链”上,当最后用户选择取消时,沿着这条“责任链”一个个通知观察者,由观察者取出备忘录,执行恢复工作。

注意:这个方法和第二个方法有点区别:第二个方法不管恢复的顺序,而第三种方法适合讲究恢复顺序的情况,例如前面提到的软件安装的撤销。

 

四、“Mementor”模式和“Flyweight”模式的结合:减少相同对象的拷贝

用于保存对象状态的“备忘录”对象,必须拥有一份和被保存对象相同的属性拷贝。

对于“备忘录”有可能导致内存消耗过大的情况,如果对象中的属性是“公用的”(即多个对象可以共享一个属性),那么我们可以考虑采用“享元模式”,减少相同属性对象的创建。但是这个方法对于属性多为运行时确定的情况作用不大。

posted on 2012-08-28 16:30  duanxz  阅读(779)  评论(0编辑  收藏  举报