在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态.如果使用一些共有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。我们需要实现对象状态的良好保存与恢复,但同时不会因此而破坏对象本身的封装性。
意图:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
我们首先看看不适用设计模式来解决对象状态恢复的情况。
public class Rectangle : ICloneable
{
int x;
int y;
int width;
int height;
public void SetValue(Rectangle r)
{
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
public Rectangle(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void MoveTo(Point p)
{
//....
}
public void ChangeWidth(int width)
{
}
public void ChangeHeight(int height)
{
}
public void Draw(Graphics graphic)
{
}
#region ICloneable 成员
public object Clone()
{
return this.MemberwiseClone();
}
#endregion
}
public class GraphicsSystem
{
//原发器对象:
//有必要对自身内部状态进行保存,然后在某个点处又需要恢复内部状态的对象
Rectangle r = new Rectangle(0, 0, 10, 10);
//备忘录对象:
//保存原发器对象的内部状态,但不提供原发器对象支持的操作
Rectangle rSaved = new Rectangle(0, 0, 10, 10);
public void Process()
{
rSaved = r.Clone();
//....
}
public void Saved_Click(object sender, EventArgs e)
{
r.SetValue(rSaved);
//....
}
}
class Program
{
static void Main(string[] args)
{
Rectangle r = new Rectangle(0, 0, 10, 10);
GraphicsSystem g = new GraphicsSystem();
g.Process(r);
}
}
上面的代码中Rectangle类实现了ICloneable接口,这个接口利用浅拷贝返回一个新的Rectangle对象。
在GraphicsSystem类中,我们定义了一个原发器对象r,和备忘录对象rSaved,在Process的时候,我们将原发器对象进行克隆保存在rSaved引用中。在Saved_Click方法中,将备忘录对象rSaved保存的值还原给原发器对象r。但这样来做,备忘录对象提过了原发器对象的一些操作,那么我们现在需要将备忘录对象抽象出来。
public class Rectangle
{
int x;
int y;
int width;
int height;
public void SetValue(Rectangle r)
{
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
public Rectangle(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void MoveTo(Point p)
{
//....
}
public void ChangeWidth(int width)
{
}
public void ChangeHeight(int height)
{
}
public void Draw(Graphics graphic)
{
}
internal RectangleMemento Creatememento()
{
RectangleMemento memento = new RectangleMemento();
memento.SetState(this.x, this.y, this.width, this.height);
return memento;
}
internal void SetMemento(RectangleMemento memento)
{
this.x = memento.x;
this.y = memento.y;
this.width
意图:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
我们首先看看不适用设计模式来解决对象状态恢复的情况。
public class Rectangle : ICloneable
{
int x;
int y;
int width;
int height;
public void SetValue(Rectangle r)
{
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
public Rectangle(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void MoveTo(Point p)
{
//....
}
public void ChangeWidth(int width)
{
}
public void ChangeHeight(int height)
{
}
public void Draw(Graphics graphic)
{
}
#region ICloneable 成员
public object Clone()
{
return this.MemberwiseClone();
}
#endregion
}
public class GraphicsSystem
{
//原发器对象:
//有必要对自身内部状态进行保存,然后在某个点处又需要恢复内部状态的对象
Rectangle r = new Rectangle(0, 0, 10, 10);
//备忘录对象:
//保存原发器对象的内部状态,但不提供原发器对象支持的操作
Rectangle rSaved = new Rectangle(0, 0, 10, 10);
public void Process()
{
rSaved = r.Clone();
//....
}
public void Saved_Click(object sender, EventArgs e)
{
r.SetValue(rSaved);
//....
}
}
class Program
{
static void Main(string[] args)
{
Rectangle r = new Rectangle(0, 0, 10, 10);
GraphicsSystem g = new GraphicsSystem();
g.Process(r);
}
}
上面的代码中Rectangle类实现了ICloneable接口,这个接口利用浅拷贝返回一个新的Rectangle对象。
在GraphicsSystem类中,我们定义了一个原发器对象r,和备忘录对象rSaved,在Process的时候,我们将原发器对象进行克隆保存在rSaved引用中。在Saved_Click方法中,将备忘录对象rSaved保存的值还原给原发器对象r。但这样来做,备忘录对象提过了原发器对象的一些操作,那么我们现在需要将备忘录对象抽象出来。
public class Rectangle
{
int x;
int y;
int width;
int height;
public void SetValue(Rectangle r)
{
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
public Rectangle(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void MoveTo(Point p)
{
//....
}
public void ChangeWidth(int width)
{
}
public void ChangeHeight(int height)
{
}
public void Draw(Graphics graphic)
{
}
internal RectangleMemento Creatememento()
{
RectangleMemento memento = new RectangleMemento();
memento.SetState(this.x, this.y, this.width, this.height);
return memento;
}
internal void SetMemento(RectangleMemento memento)
{
this.x = memento.x;
this.y = memento.y;
this.width