设计模式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.概述 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来 ...
随机推荐
- SVN的学习
SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于CVS,它采用了分支管理系统,它的设计目标就是取代CVS 为什么需要SVN 通常软件开发由多人协作开发,如果对代码文件.配置文 ...
- jaxp使用笔记
XML文件的解析技术有DOM和SAX方式,在Android中还有pull解析方式,这里不再讨论 DOM解析的方式和js中的DOM操作是一致的,DOM解析一次将文档加载入内存建立树型模型,但是如果XML ...
- CORDIC逼近算法
现在开始学习CORDIC算法 学习的博文: (1)http://blog.csdn.net/liyuanbhu/article/details/8458769 三角函数计算,Cordic 算法入门 ...
- PHP处理session跨域
同一根域名下子域名之间的跨域 ini_set('session.name', 'sid'); //设置session_id的键名 ini_set('session.use_trans_sid', 0) ...
- Vue源码(一)
入口文件 src/core/instance/index.js 中可以看到 function Vue (options) { if (process.env.NODE_ENV !== 'product ...
- python 打造一个sql注入脚本 (一)
0x00前言: 昨天刚刚看完小迪老师的sql注入篇的第一章 所以有了新的笔记. 0x01笔记: sql注入原理: 网站数据传输中,接受变量传递的值未进行过滤,导致直接带入数据库查询执行的操作. sql ...
- [Z] 将samba共享文件夹映射到linux的目录下
Linux系统下访问远程共享资源 使用mount加载共享目录: -把WinXP机器192.168.16.249上的共享目录test001映射到本地目录/wdl/下. -把Linux机器192.168. ...
- linux 远程连接服务器ftp命令整理
Ftp命令的功能是在本地机和远程机之间传送文件.该命令的一般格式如下: $ ftp 主机名/IP ftp将给出提示符,等待用户输入命令: $ ftp ftp > 最常用的命令有: ls 列出远程 ...
- PropertyGrid 重难点总结
PropertyGrid的界面组成与不同部分的名称如下图所示. 本博文不算是自己写作的,只是将PropertyGrid中的几项十分有用的功能的应用方面的文字进行一下总结,希望以后大家对Property ...
- python学习——练习题(10)
""" 题目:暂停一秒输出,并格式化当前时间. """ import sys import time def answer1(): &quo ...