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; }
}
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();
}
}
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 一個Memento的Clone
public IMemento<T> CreateMemento<T>()
{
IMemento < T > newMemento = new Memento<T>(this._state as dynamic);
return newMemento;
}
/// 設定memento為指定的memento的Clone
public void SetMemento(IMemento<T> memento)
{
this._state = (memento as dynamic).State.Clone();
}
}
=> 存放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 一個Memento的Clone
public IMemento<T> CreateMemento<T>()
{
IMemento < T > newMemento = new Memento<T>(this._state as dynamic);
return newMemento;
}
/// 設定memento為指定的memento的Clone
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();
}
}
=> 可以存放多個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 : 皮椅, 倒車雷達
=======================================
///設定初始狀態的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
Memento Design Pattern
沒有留言:
張貼留言