设计模式20:Memento 备忘录模式(行为型模式)
Memento 备忘录模式(行为型模式)
对象状态的回溯
对象状态的变化无端,如何回溯、恢复对象在某个点的状态?
动机(Motivation)
在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些共有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。
如何实现对象状态良好保存与恢复?同时又不会因而破坏对象本身的封装性。
意图(Intent)
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。——《设计模式》GoF
示例代码
public class Rectangle:ICloneable
{
private int x;
private int y;
private int width;
private 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 object Clone()
{
return this.MemberwiseClone();
}
} class GraphicSystem
{
//原发器对象
//有必要对自身的状态进行保存,然后在某个点处又需要恢复内部状态
Rectangle r=new Rectangle(,,,); //备忘录对象
//保存原发器对象内部状态,但是不提供原发器对象支持的操作
Rectangle rSaved=new Rectangle(,,,);//不符合备忘录对象的要求 public void Process()
{
rSaved = r.Clone() as Rectangle;
}
}
由于rSaved不应该提供原发器对象支持的操作,所以它不符合备忘录对象的要求。不符合单一职责原则。
解决方案一:
public class Rectangle
{
private int x;
private int y;
private int width;
private 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 CreateMemento()
{
RectangleMemento rm=new RectangleMemento();
rm.SetState(this.x,this.y,this.width,this.height);
return rm;
} public void SetMento(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;
}
} class GraphicSystem
{
//原发器对象
//有必要对自身的状态进行保存,然后在某个点处又需要恢复内部状态
Rectangle r=new Rectangle(,,,); //备忘录对象
//保存原发器对象内部状态,但是不提供原发器对象支持的操作
RectangleMemento rSaved = new RectangleMemento(); public void Process()
{
rSaved = r.CreateMemento();
}
}
解决方案二:通过序列化方式
[Serializable]
public class Rectangle
{
private int x;
private int y;
private int width;
private 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)
{
//...
} } //通用备忘录类
class GeneralMenento
{
MemoryStream rSaved = new MemoryStream(); internal void SetState(object obj)
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(rSaved, obj);
} internal object GetState()
{
BinaryFormatter bf = new BinaryFormatter();
rSaved.Seek(, SeekOrigin.Begin);
return bf.Deserialize(rSaved);
}
} class GraphicSystem
{
//原发器对象
//有必要对自身的状态进行保存,然后在某个点处又需要恢复内部状态
Rectangle r=new Rectangle(,,,); GeneralMenento rSaved = new GeneralMenento(); public void Process()
{
rSaved.SetState(r);
}
}
结构(Structure)

Memento模式的几个要点
- 备忘录(Memento)存储原发器(Originator)对象内部状态,在需要时恢复原发器状态。Memento模式适用于“由原发器管理,却又必须存储在原发器之外的信息”。
- 在实现Memento模式中,要防止原发器以外的对象访问备忘录对象。备忘录对象由两个接口,一个为原发器使用的宽接口,一个为其他对象使用的窄接口。
- 在实现Memento模式时,要考虑拷贝对象状态的效率问题,如果对象开销较大,可以采用某种增量式改变来改进Memento模式。
转载请注明出处:
作者:JesseLZJ
出处:http://jesselzj.cnblogs.com
设计模式20:Memento 备忘录模式(行为型模式)的更多相关文章
- php设计模式(一):简介及创建型模式
我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式. 一.设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用.容易被他人理解的.可靠的代码设计经验的总结. ...
- FactoryMethod工厂方法模式(创建型模式)
1.工厂方法模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只 ...
- Prototype原型模式(创建型模式)
1.原型模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只有一 ...
- 设计模式(18)--Memento(备忘录模式)--行为型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. ...
- C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)
一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配 ...
- .NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)
概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独立于如何创建.组合和表示它的那些对象.本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模 ...
- .NET设计模式(7):创建型模式专题总结(Creational Pattern)
):创建型模式专题总结(Creational Pattern) 创建型模式专题总结(Creational Pattern) --.NET设计模式系列之七 Terrylee,2006年1月 转载: ...
- 设计模式(五):PROTOTYPE原型模式 -- 创建型模式
1.定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2.适用场景 原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对 ...
- 设计模式(二): BUILDER生成器模式 -- 创建型模式
1.定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 2.适用场景 1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式 ...
- 设计模式(十四):Command命令模式 -- 行为型模式
1.概述 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来 ...
随机推荐
- XML的学习
XML是可扩展标记语言德意思,它和HTML一样都是标记语言(标签语言),不同之处在于XML可拓展,何为可拓展?在HTML中每个标签都有其特定的含义,我们不可以随便写一个标签并赋予其意义,而XML中就可 ...
- 【洛谷】P1196 银河英雄传说(并查集)
题目描述 公元五八○一年,地球居民迁至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压顶 ...
- open the flashback
1.打开flashback: 关闭数据库 启动到mount方式 SQL>startup mount; 如果归档没有打开,打开归档[因为flashback依赖Media recovery,所以在打 ...
- poj-2828 Buy Tickets(经典线段树)
/* Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 10207 Accepted: 4919 Descr ...
- xhtml和html的区别
1.XHTML要求正确嵌套 错误:<p>XHTML文档<strong>与HTML的主要区别</p></strong> 正确:<p>XHTML ...
- Julia - 字符串
字符 字符使用单引号括起来,字符是 32 位整数 julia> 'a' 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) ju ...
- Ceph系统的层次结构
Ceph存储系统的逻辑层次结构如下图所示[1]. Ceph系统逻辑层次结构自下向上,可以将Ceph系统分为四个层次: (1)基础存储系统RADOS(Reliable, Autonomic, Dis ...
- JS中的面向对象
创建对象的几种常用方式: 1,使用Object或对象字面量创建对象. 2,工厂模式创建对象. 3,构造函数模式创建对象. 4,原型模式创建对象. 使用Object或对象字面量创建对象: var stu ...
- touch python
一 使用while循环输出 1 2 3 4 5 6 8 9 10. i=0 while i<10: i=i+1 if i == 7: continue print(i) 二 求 1-100所 ...
- MongoDB出现CPU飚高,如何强制停止正在执行的操作
如果发出了一个执行耗时很长的任务给MongoDB服务器,客户端强制终止会导致任务依然在服务器端执行. 这时MongoDB提供了查询和管理正在执行任务的方式. // db.currentOp() 获得当 ...