2013年11月26日 星期二

Design Pattern : Memento

Design Pattern : Memento

Definition :
Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.




底下的範例是將剛出廠的車子(ICar)利用Memento pattern,儲存出廠的設定值。 既使後來修改ICar相關欄位,也可以還原出廠值。 注意我們這邊儲存的State是整個ICar物件,所以在儲存還原時都必須使用深層複製。



1.  IMemento :
public interface IMemento<T>
{
    T State {
get; }
}

2.  Memento : 實作IMemento,如上面提醒,這邊在存放或是回傳(restore)時,都必須呼叫該物件的深層複製方法。

public class Memento<T>:IMemento<T>
{

   
private T _state;
   
public T State
    {
       
get{
          
return (this._state as dynamic).Clone();
        }
    }
   
public Memento(T obj)
    {

       this
._state = (obj as dynamic).Clone();       
    }
}

3.  Originator :
=>
存放State
=>
CreateMemento 建立IMemento 物件(包含自己的State資訊)
=> SetMemento
由其他IMemento 物件,覆寫自己的State 一般來說這個功能可省略,因為Originator就是用來保留Snapshot,如果需要建立其他Snapshot,不應覆寫而是Create一個新的。

public class Originator<T>
{

   
private T _state;
   
public T State
    {
        
get { return _state; }
        
set { this._state = (value as dynamic).Clone(); }
    }
    /// 回傳Originator 一個MementoClone
    public IMemento<T> CreateMemento<T>()
    {
        
IMemento < T >  newMemento = new Memento<T>(this._state as dynamic);
        
return newMemento;
    }

    /// 設定memento為指定的mementoClone
    public void SetMemento(IMemento<T> memento)
    {
       
this._state = (memento as dynamic).State.Clone();
    }
}


4.  Caretaker class :
=>
可以存放多個IMemento物件,要restore時只需要指定要restore的位址即可。
/// <summary>
///
IMemento's safekeeping
/// </summary>
public class Caretaker<T>
{

   
private List<IMemento<T>> _mementos;
   
public Caretaker()
    {
      
this._mementos = new List<IMemento<T>>();
    }
   
/// Originator物件加入新的IMemento
   
public void SaveMemento(Originator<T> ori)
    {
      
this._mementos.Add(ori.CreateMemento<T>());
    }
   
   
/// Restore to an Originator object
   
public void RestoreMemento(Originator<T> ori, int index)
    {
       ori.SetMemento(
this._mementos[index]);
    }
   
   
/// Restore to a State object
   
public void RestoreState(ref T state, int index)
    {
       state = (
this._mementos[index].State as dynamic).Clone();
    }
}

5.  主程式:
///設定初始狀態的ICar車子
ICar myCar = new Focus();
myCar.Color =
Color.Yellow;
myCar.Equipment=
"皮椅, 倒車雷達";

///設定初始狀態的SnapShot
Originator<ICar> ori = new Originator<ICar>();
ori.State = myCar;
//SnapShot Clone一份存放到Caretaker
Caretaker<ICar> ct = new Caretaker<ICar>();
ct.SaveMemento(ori);

///
測試當ICar物件變更後,再Restore
ICar testCar = new Focus();
testCar.Color =
Color.Red;
testCar.Name =
"胖兔二號";
testCar.Equipment =
"Nothing";
PrinfInfo(testCar);

//Restore
ct.RestoreState(ref testCar, 0);
PrinfInfo(testCar);

結果:

Name : 胖兔二號
Color : Red
Equipment : Nothing
=======================================
Name : Focus
Color : Yellow
Equipment :
皮椅, 倒車雷達
=======================================



6.      Reference
Memento Design Pattern

沒有留言:

張貼留言