Memento备忘录模式

      有的时候需要对一个对象的状态进行恢复,象撤消按钮一样.本例中一个长方形对象,用四个数字记录长方形的状态,当变化发生的时候,有一个机制在变化之前记录状态.以下的关键都在GraphicsSystem中也就是元发器进行管理操作的.

硬编码,虽然实现了需求,但是将记录对象暴露给外部,调用者可以修改它:

ContractedBlock.gif ExpandedBlockStart.gif HardCode

using System;


class RecTangle : ICloneable
ExpandedBlockStart.gifContractedBlock.gif
{
    
int x;
    
int y;

    
int Width;
    
int Height;

    
public void SetValue(RecTangle r)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
this.x = r.x;
        
this.y = r.y;
        
this.Width = r.Width;
        
this.Height = r.Height;
    }


    
public object Clone()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
return this.MemberwiseClone();
    }


    
public RecTangle(int x, int y, int width, int height)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
this.x = x;
        
this.y = y;
        
this.Width = width;
        
this.Height = height;
    }


ContractedSubBlock.gifExpandedSubBlockStart.gif    
自身操作部分#region 自身操作部分
    
public void MoveTo
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void ChangeWidth(int width)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void ChangeHeight(int height)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void Draw(Graphic graphic)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
#endregion

}


class GraphicsSystem
ExpandedBlockStart.gifContractedBlock.gif
{
    
//元发器对象
    
//有必要对自身状态进项保存,然后再某个点处又需要恢复的对象
    RecTangle r = new RecTangle(0,0,10,10);


    
//备忘录对象-----保存元发器对象的状态,但是不提供对象支持的操作
    RecTangle rSaved = new RecTangle(001010);

    
public static void Process()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        RecTangle rSaved 
= r.Clone();
        
        
//..

    }


    
//将原来保存的值再传递回来 
    public void Saved_Click(object sender,EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        r.SetValue(rSaved);
        
    }

}

 

Memento的一种方式,编码复杂,但是给调用者的是一个窄的接口,不能操作记录对象:

ContractedBlock.gif ExpandedBlockStart.gif Memento1


using System;


class RecTangle : ICloneable
ExpandedBlockStart.gifContractedBlock.gif
{
    
int x;
    
int y;

    
int Width;
    
int Height;

    
public void SetValue(RecTangle r)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
this.x = r.x;
        
this.y = r.y;
        
this.Width = r.Width;
        
this.Height = r.Height;
    }



    
public object Clone()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
return this.MemberwiseClone();
    }


    
public RecTangle(int x, int y, int width, int height)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
this.x = x;
        
this.y = y;
        
this.Width = width;
        
this.Height = height;
    }


    
public void MoveTo
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
    }

    
public void ChangeWidth(int width)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void ChangeHeight(int height)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void Draw(Graphic graphic)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }

    
public RectangleMemento CreateMemento()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        RectangleMemento rm 
= new RectangleMemento();
        rm.SetState(
this.x, this.y, this.Width, this.Height);
        
return rm;
    }


    
public void SetMemento(RecTangle rm)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
this.x = rm.x;
        
this.y = rm.y;
        
this.Width = rm.Width;
        
this.Height = rm.Height;
    }


}



//仅仅作为一个状态存储的对象,对于本例来说就是4个数字
public class RectangleMemento
ExpandedBlockStart.gifContractedBlock.gif
{
    
internal int x;
    
internal int y;

    
internal int Width;
    
internal int Height;

    
internal void SetState(int x, int y, int width, int height)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
this.x = x;
        
this.y = y;
        
this.Width = width;
        
this.Height = height;
    }

}



//GraphicsSystem 处于另外的程序集中

class GraphicsSystem
ExpandedBlockStart.gifContractedBlock.gif
{
    
//元发器对象
    
//有必要对自身状态进项保存,然后再某个点处又需要恢复的对象
    RecTangle r = new RecTangle(001010);


    
//备忘录对象-----保存元发器对象的状态,但是不提供对象支持的操作
    RectangleMemento rSaved = new RectangleMemento();


    
//用rSaved保存元发状态
    public static void Process()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        RecTangle rSaved 
= rSaved.CreateMemento();
        
//..

    }


    
//回调
    public void Saved_Click(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        r.SetMemento(rSaved);
    }

}

 

 

一种好的做法就是把需要记录状态的对象做成一个内存流进行保存:

ContractedBlock.gif ExpandedBlockStart.gif MementoStream


using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

ExpandedBlockStart.gifContractedBlock.gif
/**//// <summary>
/// 序列化
/// </summary>
/// 


[Serializable]
class RecTangle : ICloneable
ExpandedBlockStart.gifContractedBlock.gif
{
    
int x;
    
int y;

    
int Width;
    
int Height;

    
public RecTangle(int x, int y, int width, int height)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
this.x = x;
        
this.y = y;
        
this.Width = width;
        
this.Height = height;
    }


    
public void MoveTo
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void ChangeWidth(int width)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void ChangeHeight(int height)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }
    
public void Draw(Graphic graphic)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{ }

}


//GraphicsSystem 处于另外的程序集中

class GraphicsSystem
ExpandedBlockStart.gifContractedBlock.gif
{
    
//元发器对象
    
//有必要对自身状态进项保存,然后再某个点处又需要恢复的对象
    RecTangle r = new RecTangle(001010);


    
//备忘录对象-----保存元发器对象的状态,但是不提供对象支持的操作
    
//RectangleMemento rSaved = new RectangleMemento();
    MemoryStream rSaved = new MemoryStream();

    
public static void Process()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
//先序列化将状态作为rSaved保存下来
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(r, rSaved);


        
//然后做其它操作..

    }


    
//触发恢复事件
    public void Saved_Click(object sender, EventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
//反序列化
        BinaryFormatter bf = new BinaryFormatter();
        rSaved.Seek(
0,SeekOrigin);
        r 
= (RecTangle)bf.Deserialize(rSaved);
        
    }

}


 

泛型的记录,这里仅仅列出一个类的代码,其他应该与上面差别不大 :

ContractedBlock.gif ExpandedBlockStart.gif 泛啦
class GeneralMementor
ExpandedBlockStart.gifContractedBlock.gif
{
    MemoryStream rSaved 
= new MemoryStream();

    
public GeneralMemento(Factory factory)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        rSaved 
= factory.CreateStream();
    }


    
internal void SetState(object obj)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        BinaryFormatter bf 
= new BinaryFormatter();
        bf.Serialize(obj,rSaved);
    }


    
internal object GetState()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        BinaryFormatter bf 
= new BinaryFormatter();
        rSaved.Seek(
0,SeekOrigin);
        
object obj = (RecTangle)bf.Deserialize(rSaved);

        
return obj;
    }

 
}

转载于:https://www.cnblogs.com/stupid-fool/archive/2009/05/24/1488349.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值