C#基础Memento备忘录模式(行为型模式)
在软件构造过程中,一些对象的状态处于转换过程中,可能需要程序追溯到对象之前某一点的状态。如果用一些通用接口让其他对象得到对象的状态,那么对象的详细实现就会暴露出来。我们需要很好地保存和恢复对象的状态,但同时又不会破坏对象本身的封装。
Examda提示:捕获对象的内部状态,并在不破坏封装的情况下将其保存在对象外部。通过这种方式,对象可以在以后恢复到其原始保存状态。
首先,我们来看看解决对象状态恢复问题的不适用的设计模式。
公共类Rectangle:I cloneable
{
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 move to(p点)
{
//....
}
Public void change width(int width)
{
}
{
}
Public void draw(graphics graphic)
{
}
# regional able member
Public object Clone()
{
return this .memberwisecolone();
}
# end region
}
公共类图形系统
{
/initiator对象:
//需要保存其内部状态,然后需要在某个时候恢复。
// memo对象:
/保存发起方对象的内部状态,但不提供发起方对象支持的操作
rectangle r saved = new rectangle(0,0,10,10);
public void Process()
{
RS aved = r . Clone();
//....
}
public void Saved _ Click(对象发送方,EventArgs e)
{
r . SetValue(RS aved);
//....
}
}
类程序
{
static void Main(string[]args)
{
Rectangle r = new Rectangle(0,0,10,10);
graphics system g = new graphics system();
g . Process(r);
}
}
上面代码中的Rectangle类实现了ICloneable接口,该接口使用shallow copy返回一个新的Rectangle对象
在GraphicsSystem类中,我们定义了一个initiator对象R和一个memo对象rSaved。在这个过程中,我们克隆启动器对象并将其保存在R中。在Saved_Click方法中,memo对象R的保存值被恢复到启动器对象R中..但是这样做的时候,memo对象提到了initiator对象的一些操作,所以我们现在需要抽象memo对象。
公共类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 move to(p点)
{
//....
}
public void change width(int width)
{
}
{
}
public void Draw(Graphics Graphics)
{
}
internal rectangle memento create memento()
{
rectangle memento = new rectangle memento();纪念品。SetState(this.x,this.y,this.width,this . height);
返回纪念品;
}
内部void set memento(rectangle memento memento)
{
this . x = memento . x;
this . y = memento . y;
this . width = memento . width;
this . height = memento . height;
}
}
内部类rectangle memento
{
internal int x;
internal int y;
内部int宽度;
内部int高度;
内部void SetState(int x,int y,int width,int height)
{
this . x = x;
this . y = y;
this . width = width;
this . height = height;
}
}
公共类图形系统
{
/initiator对象:
//需要保存其内部状态,然后在某个时刻恢复的对象
rectangle r .
//Memento对象:
/保存Initiator对象的内部状态,但不提供Initiator对象支持的操作
rectangle memo r saved = new rectangle memo();
public void Process(Rectangle r)
{
RS aved = r . create memento();
//....
}
public void Saved _ Click(object sender,EventArgs e)
{
r . set memento(RS aved);
//......
}
在上面的代码中,我们将memo对象抽象为RectangleMemento类,该类只保存initiator对象的基本值,不提供其他操作。而且,我们将RectangleMemento类及其内部成员声明为internal,只能使程序集。
实现要点:
memo存储发起方对象的内部状态,必要时恢复发起方状态。Memento模式适用于发起方管理的信息,但必须存储在发起方之外
在实现Memento模式时,为了防止发起方以外的对象定位memo对象,memo对象有两个接口,一个是发起方使用的宽接口,一个是其他对象使用的窄接口
在实现Memento模式时,要考虑复制对象状态的效率。如果对象开销较大,可以采用一些增量变化来跟进Memnto模式
。在上面的例子中,Rectangle看到的是RectangleMemento的宽接口,即SetState方法,而GraphicsSystem看到的是窄接口,即RectangleMemento的构造函数以及Creatememento和SetMemento的方法。当对象很大时,在。net,如DataSet,保存对象的状态可能会导致效率问题,并占用大量内存。
下面的代码演示了通过使用序列化
[serializable]
公共类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 move to(p点)
{
//....
}
public void change width(int width)
}
public void change height(int height)
{
}
{
}
public general mementor create memento()
{
general mementor memento = new general mementor();纪念品。SetState(this);
返回纪念品;
}
public void set memento(general mementor memento)
{
Rectangle r = memento。GetState()为矩形;
SetValue(r);
}
}
public类general mementor
{
memory stream RS aved = new memory stream();
内部void SetState(object obj)
{
binary formatter BF = new binary formatter();
bf。Serialize(rSaved,obj);
}
内部对象GetState()
{
binary formatter BF = new binary formatter();
rSaved。Seek(0,SeekOrigin。end);
object obj = bf。反序列化(rSaved);
return obj;
}
}
公共类图形系统
{
/Initiator对象:
//需要保存其内部状态,然后在某个点恢复的对象
rectangle r .
generalmentor memntor = null;
// memo对象:
/保存发起方对象的内部状态,但不提供发起方对象支持的操作
public void process(rectangle r)
{
memo = r . create memo();
//....
}
public void Saved _ Click(object sender,EventArgs e)
{
r . set memento(memntor);
//......
}
在上面的代码中,我们可以看到矩形发起方保存在内存流中,当它被恢复时,内存流中的对象也被恢复。我们可以进一步抽象和保存任何流中的对象,所以这里不做演示。
0条评论