备忘录(Memento)模式
2007-08-01 14:31
344 查看
对象状态的回溯
对象状态的变化无端,如何回溯/恢复对象在某个点的状态?
1、动机
在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。
如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。
2、意图
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
3、图
4、代码
v1.0
public class Rectangle : ICloneable
{
int x;
int y;
int width;
int height;
public Rectangle( int x , int y , int width , int height )
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public object Clone()
{
return this.MemberwiseClone();
}
public void SetValue( Rectangle r )
{
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
public void MoveTo(Point p)
{
}
public void ChangeWidth( int width )
{
}
public void ChangeHeight( int height )
{
}
public void Draw( Graphic graphic )
{
}
}
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 Process( )
{
rSaved = r.Clone();
//....
}
public void Saved_Click(object sender , EventAgrs e )
{
r.SetValue( rSaved );
}
}
v2.0
public class Rectangle
{
int x;
int y;
int width;
int 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( Graphic graphic )
{
}
public RectangleMemento CreateMemonto()
{
RectangleMemento rm = new RectangleMemento();
rm.SetState( this.x , this.y , this.width , this.height);
return tm;
}
public void SetMemento(RectangleMemento rm)
{
this.x = rm.x;
this.y = rm.y;
this.width = rm.width;
this.height = rm.height;
}
}
public class RectangleMemento
{
internal int x;
internal int y;
internal int width;
internal int height;
internal void SetState( int x ,int y , int width int height )
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
//GraphicsSystem处于另外的程序集中
public class GraphicsSystem
{
//原发器对象
//有必要对自身状态进行保存,然后在某个点处又需要恢复内部状态人的对象
Rectangle r = new Rectangle(0,0,10,10);
//备忘录对象
//保存原发器对象的状态,但是不提供原发器对象支持的操作
RectangleMemento rSaved = new RectangleMemento ();
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Saved_Click(object sender , EventAgrs e )
{
r.SetMemento( rSaved );
}
}
v3.0
[Serizable]
public class Rectangle
{
int x;
int y;
int width;
int 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( Graphic graphic )
{
}
public GeneralMemontor CreateMemonto()
{
GeneralMemontor gm = new RectangleMemento();
gm.SetState( this );
return gm;
}
public void SetMemento(GeneralMemontor memento)
{
Rectangle r = (Rectangle)memento.GetState();
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
}
class GeneralMemontor
{
Stream rSaved;
public GeneralMemontor(Factory factory)
{
rSaved = factory.CreateStream() ;
}
internal void SetState(object obj)
{
BinaryFomatter bf = new BinaryFomatter();
bf.Serialize( obj , rSaved );
}
internal obj GetState()
{
BinaryFomatter bf = new BinaryFomatter();
rSaved.Seek( 0 , Seek.Original );
object obj = bf.DeSerialize( rSaved );
return obj;
}
}
public class GraphicsSystem
{
//原发器对象
//有必要对自身状态进行保存,然后在某个点处又需要恢复内部状态人的对象
Rectangle r = new Rectangle(0,0,10,10);
//备忘录对象
//保存原发器对象的状态,但是不提供原发器对象支持的操作
GeneralMemontor rSaved = new GeneralMemontor();
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Saved_Click(object sender , EventAgrs e )
{
r.SetMemento( rSaved );
}
}
------------------------------------------------------------------------------------------------------------
白箱设计
public class Originator
{
private string state;
public Memento createMemento()
{
return new Memento( state );
}
public void restoreMemento( Memento memento )
{
this.state = memento.State;
}
public string State
{
get
{
return state;
}
set
{
state = value;
}
}
}
public class Memento
{
private string state;
public Memento( string state )
{
this.state = state;
}
public string State
{
get
{
return state;
}
set
{
state = value;
}
}
}
public class Caretaker
{
private Memento memento;
public Memento retrieveMemento()
{
return this.memento;
}
public void savaMemento( Memento memento )
{
this.memento = memento;
}
}
public class Client
{
private static Originator o = new Originator();
private static Caretaker c = new Caretaker();
public static void main(string[] args)
{
o.State = "On";
//保存
c.savaMemento( o.createMemento() );
o.State = "Off";
//恢复
o.restoreMemento( c.retrieveMemento() );
}
}
黑箱设计
public interface MementoIF
{
}
public class Originator
{
private string state;
public MementoIf createMemento()
{
return new Memento( this.state );
}
public void restoreMemento( MementoIf memento )
{
Memento aMemento = (Memento)memento
this.state = aMemento.SavedState;
}
public string State
{
get
{
return state;
}
set
{
state = value;
}
}
public class Memento : MementoIF
{
private string savedState;
public Memento( string state )
{
this.savedState = state;
}
public string SavedState
{
get
{
return savedState;
}
set
{
savedState = value;
}
}
}
}
public class Caretaker
{
private MementoIF memento;
public MementoIF retrieveMemento()
{
return this.memento;
}
public void savaMemento( MementoIF memento )
{
this.memento = memento;
}
}
public class Client
{
private static Originator o = new Originator();
private static Caretaker c = new Caretaker();
public static void main(string[] args)
{
o.State = "On";
//保存
c.savaMemento( o.createMemento() );
o.State = "Off";
//恢复
o.restoreMemento( c.retrieveMemento() );
}
}
5、要点
(1) 备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器状态。
Memento模式适用于“由原发器管理,却又必须存储在原发器之外的信息”
(2) 在实现Memento模式中,要防止原发器以为的对象访问备忘录对象,备忘录对象有两个接口,一个为原发器使用的宽接口;一个为其他对象使用的窄接口。
(3) 在实现Memento模式时,要考虑拷贝对象状态的效率问题,如果对象开销比较大,可以采用某种增量式改变来改进Memento模式。
对象状态的变化无端,如何回溯/恢复对象在某个点的状态?
1、动机
在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。
如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。
2、意图
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
3、图
4、代码
v1.0
public class Rectangle : ICloneable
{
int x;
int y;
int width;
int height;
public Rectangle( int x , int y , int width , int height )
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public object Clone()
{
return this.MemberwiseClone();
}
public void SetValue( Rectangle r )
{
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
public void MoveTo(Point p)
{
}
public void ChangeWidth( int width )
{
}
public void ChangeHeight( int height )
{
}
public void Draw( Graphic graphic )
{
}
}
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 Process( )
{
rSaved = r.Clone();
//....
}
public void Saved_Click(object sender , EventAgrs e )
{
r.SetValue( rSaved );
}
}
v2.0
public class Rectangle
{
int x;
int y;
int width;
int 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( Graphic graphic )
{
}
public RectangleMemento CreateMemonto()
{
RectangleMemento rm = new RectangleMemento();
rm.SetState( this.x , this.y , this.width , this.height);
return tm;
}
public void SetMemento(RectangleMemento rm)
{
this.x = rm.x;
this.y = rm.y;
this.width = rm.width;
this.height = rm.height;
}
}
public class RectangleMemento
{
internal int x;
internal int y;
internal int width;
internal int height;
internal void SetState( int x ,int y , int width int height )
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
//GraphicsSystem处于另外的程序集中
public class GraphicsSystem
{
//原发器对象
//有必要对自身状态进行保存,然后在某个点处又需要恢复内部状态人的对象
Rectangle r = new Rectangle(0,0,10,10);
//备忘录对象
//保存原发器对象的状态,但是不提供原发器对象支持的操作
RectangleMemento rSaved = new RectangleMemento ();
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Saved_Click(object sender , EventAgrs e )
{
r.SetMemento( rSaved );
}
}
v3.0
[Serizable]
public class Rectangle
{
int x;
int y;
int width;
int 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( Graphic graphic )
{
}
public GeneralMemontor CreateMemonto()
{
GeneralMemontor gm = new RectangleMemento();
gm.SetState( this );
return gm;
}
public void SetMemento(GeneralMemontor memento)
{
Rectangle r = (Rectangle)memento.GetState();
this.x = r.x;
this.y = r.y;
this.width = r.width;
this.height = r.height;
}
}
class GeneralMemontor
{
Stream rSaved;
public GeneralMemontor(Factory factory)
{
rSaved = factory.CreateStream() ;
}
internal void SetState(object obj)
{
BinaryFomatter bf = new BinaryFomatter();
bf.Serialize( obj , rSaved );
}
internal obj GetState()
{
BinaryFomatter bf = new BinaryFomatter();
rSaved.Seek( 0 , Seek.Original );
object obj = bf.DeSerialize( rSaved );
return obj;
}
}
public class GraphicsSystem
{
//原发器对象
//有必要对自身状态进行保存,然后在某个点处又需要恢复内部状态人的对象
Rectangle r = new Rectangle(0,0,10,10);
//备忘录对象
//保存原发器对象的状态,但是不提供原发器对象支持的操作
GeneralMemontor rSaved = new GeneralMemontor();
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Process( )
{
rSaved = r.CreateMemonto();
//....
}
public void Saved_Click(object sender , EventAgrs e )
{
r.SetMemento( rSaved );
}
}
------------------------------------------------------------------------------------------------------------
白箱设计
public class Originator
{
private string state;
public Memento createMemento()
{
return new Memento( state );
}
public void restoreMemento( Memento memento )
{
this.state = memento.State;
}
public string State
{
get
{
return state;
}
set
{
state = value;
}
}
}
public class Memento
{
private string state;
public Memento( string state )
{
this.state = state;
}
public string State
{
get
{
return state;
}
set
{
state = value;
}
}
}
public class Caretaker
{
private Memento memento;
public Memento retrieveMemento()
{
return this.memento;
}
public void savaMemento( Memento memento )
{
this.memento = memento;
}
}
public class Client
{
private static Originator o = new Originator();
private static Caretaker c = new Caretaker();
public static void main(string[] args)
{
o.State = "On";
//保存
c.savaMemento( o.createMemento() );
o.State = "Off";
//恢复
o.restoreMemento( c.retrieveMemento() );
}
}
黑箱设计
public interface MementoIF
{
}
public class Originator
{
private string state;
public MementoIf createMemento()
{
return new Memento( this.state );
}
public void restoreMemento( MementoIf memento )
{
Memento aMemento = (Memento)memento
this.state = aMemento.SavedState;
}
public string State
{
get
{
return state;
}
set
{
state = value;
}
}
public class Memento : MementoIF
{
private string savedState;
public Memento( string state )
{
this.savedState = state;
}
public string SavedState
{
get
{
return savedState;
}
set
{
savedState = value;
}
}
}
}
public class Caretaker
{
private MementoIF memento;
public MementoIF retrieveMemento()
{
return this.memento;
}
public void savaMemento( MementoIF memento )
{
this.memento = memento;
}
}
public class Client
{
private static Originator o = new Originator();
private static Caretaker c = new Caretaker();
public static void main(string[] args)
{
o.State = "On";
//保存
c.savaMemento( o.createMemento() );
o.State = "Off";
//恢复
o.restoreMemento( c.retrieveMemento() );
}
}
5、要点
(1) 备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器状态。
Memento模式适用于“由原发器管理,却又必须存储在原发器之外的信息”
(2) 在实现Memento模式中,要防止原发器以为的对象访问备忘录对象,备忘录对象有两个接口,一个为原发器使用的宽接口;一个为其他对象使用的窄接口。
(3) 在实现Memento模式时,要考虑拷贝对象状态的效率问题,如果对象开销比较大,可以采用某种增量式改变来改进Memento模式。
相关文章推荐
- 设计模式-行为设计模式:备忘录模式 Memento
- (Boolan)C++设计模式 <十> ——状态模式(State)和备忘录(Memento)
- 设计模式的征途—20.备忘录(Memento)模式
- 《模式——工程化实现及扩展》(设计模式C# 版)《备忘录模式 Memento》——“自我检验" 参考答案
- JAVA设计模式-备忘录模式-Memento-游戏备份存档
- 设计模式学习笔记(十七)—Memento备忘录模式
- Gof设计模式之备忘录模式 (Memento)
- Memento 备忘录模式 使用Boost智能指针实现
- HeadFirst 设计模式学习笔记22-- 备忘录(Memento)模式拾零
- 设计模式—Memento备忘录模式
- 行为模式:Memento(备忘录)
- 设计模式_Memento_备忘录模式
- Memento(备忘录)——对象行为模式
- 设计模式十九:memento(备忘录)——对象行为型模式
- 行为型模式-Memento ( 备忘录模式 )
- 3.6 Memento(备忘录) -- 对象行为型模式
- 备忘录模式——Memento
- 分分钟搞定备忘录模式(Memento)
- 设计模式----Memento(备忘录)
- 设计模式学习-Memento(备忘录)