Robin's Blog

记录 积累 学习 成长

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Memento模式也叫备忘录模式,是由GoF提出的23种软件设计模式的一种。Memento模式是行为模式之一,它的作用是保存对象的内部状态,并在需要的时候(undo/rollback)恢复对象以前的状态。


本文介绍设计模式中的(Memento)模式的概念,用法,以及实际应用中怎么样使用Memento模式进行开发。
Memento模式的概念
Memento模式是行为模式之一,它的作用是保存对象的内部状态,并在需要的时候(undo/rollback)恢复对象以前的状态。
Memento的英文原意包含有纪念物,快照,备忘录的意思,Memento模式取意使用memento来保存对象现有的状态,从而可以在将来需要的时候把这个对象还原到以前被保存的状态。

Memento模式的角色:
Originator(原生者)
    需要被保存状态以便恢复的那个对象。
Memento(备忘录)
    该对象由Originator创建,主要用来保存Originator的内部状态。
Caretaker(管理者)
    负责在适当的时间保存/恢复Originator对象的状态。


Memento模式的应用场景
如果一个对象需要保存状态并可通过undo或rollback等操作恢复到以前的状态时,可以使用Memento模式。
1)一个类需要保存它的对象的状态(相当于Originator角色)
2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色)
3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存
4)undo或rollback操作时,通过Caretaker保存的Memento恢复Originator对象的状态


Memento模式的应用范例
Memento模式比较简单,我们只需要按照上面所介绍的步骤就可以实现Memento模式。

下面,我们使用Memento模式模拟下面这个操作:
对字符串做append操作,每操作一次计数器+1,这个操作由Originator类实现;另外,我们需要在适当的时候恢复操作之前的状态加以回退(undo)。
文件一览:
Client
    测试类。
Memento
    Memento备忘录类。保持Originator对象的状态。
Originator
    需要保持/恢复状态的类。该类有2个状态需要保存String data以及int count。
Caretaker
    管理者类,根据情况可以省略。

代码:
  1. public class Client {  
  2.   
  3.     /** 
  4.      * Test Memento Pattern 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         //创建目标对象  
  8.         Originator org = new Originator();  
  9.         org.setData("aaa");  
  10.         System.out.println("Original value: [" + org.getData() + ", " + org.getCount() + "]");  
  11.   
  12.         //创建目标对象的一个快照  
  13.         Memento snapshot = org.createMemento();  
  14.         //通过Caretaker保存此快照  
  15.         Caretaker caretaker = new Caretaker();  
  16.         caretaker.setMemento(snapshot);  
  17.   
  18.         //操作目标对象改变目标对象的值  
  19.         org.append("bbb");  
  20.         org.append("ccc");  
  21.         System.out.println("Updated value: [" + org.getData() + ", " + org.getCount() + "]");  
  22.   
  23.           
  24.         //还原  
  25.         org.setMemento(caretaker.getMemento());  
  26.         System.out.println("Restored value: [" + org.getData() + ", " + org.getCount() + "]");  
  27.     }  
  28.   
  29. }  
  30.   
  31.   
  32. /** 
  33.  * Originator 
  34.  * 
  35.  */  
  36. class Originator {  
  37.     private String data = "";  
  38.     private int count = 0;  
  39.   
  40.     public void append(String expr) {  
  41.         data += expr;  
  42.         count++;  
  43.     }  
  44.   
  45.     public String getData() {  
  46.         return data;  
  47.     }  
  48.   
  49.     public void setData(String data) {  
  50.         this.data = data;  
  51.     }  
  52.   
  53.     public Memento createMemento() {  
  54.         return new Memento(data, count);  
  55.     }  
  56.   
  57.     public void setMemento(Memento memento) {  
  58.         data = memento.getData();  
  59.         count = memento.getCount();  
  60.     }  
  61.   
  62.     public int getCount() {  
  63.         return count;  
  64.     }  
  65.   
  66.     public void setCount(int count) {  
  67.         this.count = count;  
  68.     }  
  69. }  
  70.   
  71.   
  72. /** 
  73.  * Memento 
  74.  * 
  75.  */  
  76. class Memento {  
  77.     private String data;  
  78.     private int count = 0;  
  79.   
  80.     public Memento(String data, int count) {  
  81.         this.data = data;  
  82.         this.count = count;  
  83.     }  
  84.   
  85.     public String getData() {  
  86.         return data;  
  87.     }  
  88.       
  89.     public int getCount() {  
  90.         return count;  
  91.     }  
  92.   
  93.     public void setCount(int count) {  
  94.         this.count = count;  
  95.     }  
  96. }  
  97.   
  98.   
  99. /** 
  100.  * Caretaker 
  101.  * 
  102.  */  
  103. class Caretaker {  
  104.     Memento memento;  
  105.   
  106.     public Memento getMemento() {  
  107.         return memento;  
  108.     }  
  109.   
  110.     public void setMemento(Memento memento) {  
  111.         this.memento = memento;  
  112.     }  
  113. }  



执行Client,输出结果:
C:\Memento>javac *.java
C:\Memento>java Client
Original value: [aaa, 0]
Updated value: [aaabbbccc, 2]
Restored value: [aaa, 0]
C:\Memento>
Originator对象的初始状态为[aaa, 0],经过某些操作,变为[aaabbb, 2],经过Memento模式处理之后,又复原到了[aaa, 0]。

后记:
1,Command模式也可以用来恢复对象的状态,一般Command模式可以支持多级状态的回退,Memento只是简单的恢复(一级);其实,Command模式在每一个undo中,可以使用Memento来保存对象的状态。
- Command can use Memento to maintain the state required for an undo operation. [GoF, p242]
2,从Originator对象到Memento的过程是一个对象拷贝的操作,Java语言的克隆与深层次克隆技术入门与精通 一文比较深入地介绍了对象间的拷贝技术。
posted on 2009-08-31 17:27  Robin99  阅读(294)  评论(0)    收藏  举报