動機:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外儲存這個狀態。這樣就可以將該對象恢複到原先儲存的狀態。
情境:此處以圖形系統為例,圓為原發器,該系統對圓進行處理,並儲存可恢複狀態序列。
結構圖
代碼
namespace DesignPattern.Memento
{
/**//// <summary>
/// 原發器
/// </summary>
public class Round
{
private Point centerPoint;
private int radius;
public Round(Point centerPoint, int radius)
{
this.centerPoint = centerPoint;
this.radius = radius;
}
public RoundMemento CreateMemento()
{
RoundMemento memento = new RoundMemento();
memento.SetState(this.centerPoint, this.radius);
return memento;
}
public void SetMemento(RoundMemento memento)
{
this.centerPoint = memento.centerPoint;
this.radius = memento.radius;
}
public void Move(Point point)
{
}
public void SetLength(int radius)
{
}
}
/**//// <summary>
/// 備忘錄
/// </summary>
public class RoundMemento
{
internal Point centerPoint;
internal int radius;
public RoundMemento()
{
}
internal void SetState(Point centerPoint, int radius)
{
this.centerPoint = centerPoint;
this.radius = radius;
}
}
}
namespace DesignPattern.Memento
{
public class GraphicsSystem
{
Round round = new Round (new Point(), 10);
IList<RoundMemento> mementos;
public GraphicsSystem()
{
mementos = new List<RoundMemento>();
}
public void Process()
{
mementos.Add(round.CreateMemento());
// 操作圓
}
public void Undo(int index)
{
round.SetMemento(mementos[index]);
}
}
}
要點:
1、備忘錄(Memento)儲存原發器(Originator)對象的內部狀態,在需要時恢複原發器狀態。本模式適用於“由原發器管理,卻又必須儲存在原發器之外的資訊”。
2、實現本模式時,要防止原發器以外的對象訪問備忘錄對象。備忘錄對象有兩個介面,一個為原發器使用的寬介面,一個為其他對象使用的窄介面。
3、實現本模式時,要考慮拷貝對象狀態的效率問題,如果對象開銷比較大,可以採用某種增量式改變來改進本模式。