有的时候需要对一个对象的状态进行恢复,象撤消按钮一样.本例中一个长方形对象,用四个数字记录长方形的状态,当变化发生的时候,有一个机制在变化之前记录状态.以下的关键都在GraphicsSystem中也就是元发器进行管理操作的.
硬编码,虽然实现了需求,但是将记录对象暴露给外部,调用者可以修改它:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
HardCode
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
using System;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
class RecTangle : ICloneable
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
int x;
int y;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
int Width;
int Height;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void SetValue(RecTangle r)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = r.x;
this.y = r.y;
this.Width = r.Width;
this.Height = r.Height;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public object Clone()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return this.MemberwiseClone();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public RecTangle(int x, int y, int width, int height)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = x;
this.y = y;
this.Width = width;
this.Height = height;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
自身操作部分#region 自身操作部分
public void MoveTo
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void ChangeWidth(int width)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void ChangeHeight(int height)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void Draw(Graphic graphic)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
#endregion
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
class GraphicsSystem
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
//元发器对象
//有必要对自身状态进项保存,然后再某个点处又需要恢复的对象
RecTangle r = new RecTangle(0,0,10,10);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//备忘录对象-----保存元发器对象的状态,但是不提供对象支持的操作
RecTangle rSaved = new RecTangle(0, 0, 10, 10);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public static void Process()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RecTangle rSaved = r.Clone();
//
..
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//将原来保存的值再传递回来
public void Saved_Click(object sender,EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
r.SetValue(rSaved);
}
}
Memento的一种方式,编码复杂,但是给调用者的是一个窄的接口,不能操作记录对象:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Memento1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
using System;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
class RecTangle : ICloneable
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
int x;
int y;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
int Width;
int Height;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void SetValue(RecTangle r)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = r.x;
this.y = r.y;
this.Width = r.Width;
this.Height = r.Height;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public object Clone()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return this.MemberwiseClone();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public RecTangle(int x, int y, int width, int height)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = x;
this.y = y;
this.Width = width;
this.Height = height;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void MoveTo
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
}
public void ChangeWidth(int width)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void ChangeHeight(int height)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void Draw(Graphic graphic)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public RectangleMemento CreateMemento()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RectangleMemento rm = new RectangleMemento();
rm.SetState(this.x, this.y, this.Width, this.Height);
return rm;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void SetMemento(RecTangle rm)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = rm.x;
this.y = rm.y;
this.Width = rm.Width;
this.Height = rm.Height;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//仅仅作为一个状态存储的对象,对于本例来说就是4个数字
public class RectangleMemento
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
internal int x;
internal int y;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
internal int Width;
internal int Height;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
internal void SetState(int x, int y, int width, int height)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = x;
this.y = y;
this.Width = width;
this.Height = height;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//GraphicsSystem 处于另外的程序集中
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
class GraphicsSystem
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
//元发器对象
//有必要对自身状态进项保存,然后再某个点处又需要恢复的对象
RecTangle r = new RecTangle(0, 0, 10, 10);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//备忘录对象-----保存元发器对象的状态,但是不提供对象支持的操作
RectangleMemento rSaved = new RectangleMemento();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//用rSaved保存元发状态
public static void Process()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RecTangle rSaved = rSaved.CreateMemento();
//
..
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//回调
public void Saved_Click(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
r.SetMemento(rSaved);
}
}
一种好的做法就是把需要记录状态的对象做成一个内存流进行保存:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
MementoStream
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//// <summary>
/// 序列化
/// </summary>
///
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
[Serializable]
class RecTangle : ICloneable
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
int x;
int y;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
int Width;
int Height;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public RecTangle(int x, int y, int width, int height)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.x = x;
this.y = y;
this.Width = width;
this.Height = height;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void MoveTo
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void ChangeWidth(int width)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void ChangeHeight(int height)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
public void Draw(Graphic graphic)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//GraphicsSystem 处于另外的程序集中
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
class GraphicsSystem
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
//元发器对象
//有必要对自身状态进项保存,然后再某个点处又需要恢复的对象
RecTangle r = new RecTangle(0, 0, 10, 10);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//备忘录对象-----保存元发器对象的状态,但是不提供对象支持的操作
//RectangleMemento rSaved = new RectangleMemento();
MemoryStream rSaved = new MemoryStream();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public static void Process()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//先序列化将状态作为rSaved保存下来
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(r, rSaved);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//然后做其它操作
..
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//触发恢复事件
public void Saved_Click(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//反序列化
BinaryFormatter bf = new BinaryFormatter();
rSaved.Seek(0,SeekOrigin);
r = (RecTangle)bf.Deserialize(rSaved);
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
泛型的记录,这里仅仅列出一个类的代码,其他应该与上面差别不大 :
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
泛啦
class GeneralMementor
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
MemoryStream rSaved = new MemoryStream();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public GeneralMemento(Factory factory)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
rSaved = factory.CreateStream();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
internal void SetState(object obj)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(obj,rSaved);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
internal object GetState()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
BinaryFormatter bf = new BinaryFormatter();
rSaved.Seek(0,SeekOrigin);
object obj = (RecTangle)bf.Deserialize(rSaved);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return obj;
}
}