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 备忘录模式(行为型模式)的更多相关文章

  1. php设计模式(一):简介及创建型模式

    我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式. 一.设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用.容易被他人理解的.可靠的代码设计经验的总结. ...

  2. FactoryMethod工厂方法模式(创建型模式)

    1.工厂方法模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只 ...

  3. Prototype原型模式(创建型模式)

    1.原型模式解决的问题 现在有一个抽象的游戏设施建造系统,负责构建一个现代风格和古典风格的房屋和道路. 前提:抽象变化较慢,实现变化较快(不稳定) 整个抽象的游戏设施建造系统相对变化较慢,本例中只有一 ...

  4. 设计模式(18)--Memento(备忘录模式)--行为型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. ...

  5. C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)

    一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配 ...

  6. .NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)

    概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独立于如何创建.组合和表示它的那些对象.本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模 ...

  7. .NET设计模式(7):创建型模式专题总结(Creational Pattern)

    ):创建型模式专题总结(Creational Pattern)    创建型模式专题总结(Creational Pattern) --.NET设计模式系列之七 Terrylee,2006年1月 转载: ...

  8. 设计模式(五):PROTOTYPE原型模式 -- 创建型模式

    1.定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2.适用场景 原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对 ...

  9. 设计模式(二): BUILDER生成器模式 -- 创建型模式

    1.定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 2.适用场景 1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式 ...

  10. 设计模式(十四):Command命令模式 -- 行为型模式

    1.概述         在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来 ...

随机推荐

  1. AtomicHashMap

    folly/AtomicHashmap.h folly/AtomicHashmap.h introduces a synchronized UnorderedAssociativeContainer ...

  2. linux-强制断开远程tcp连接

    最近在做日常维护,搭建了socks代理,但是socks代理服务已经关闭了,由于其他机器还在和我的服务器保持tcp长连接 e.g. tcp ESTAB Google了一下,没找到特别好的办法,例如ipt ...

  3. [安全分享]斗鱼&360补天沙龙分享-跨域资源那些事

    [安全分享]斗鱼&360补天沙龙分享-跨域资源那些事 主要内容: 文件: http://scan.javasec.cn/补天&斗鱼-跨域资源那些事.pdf

  4. martin/docker-cleanup-volumes

    https://hub.docker.com/r/martin/docker-cleanup-volumes/

  5. 转:Numpy教程

    因为用到theano写函数的时候饱受数据结构困扰 于是上网找了一篇numpy教程(theano的数据类型是基于numpy的) 原文排版更好,阅读体验更佳: http://phddreamer.blog ...

  6. CentOS7.6安装稳定版Nginx

    官网地址:http://nginx.org/en/linux_packages.html#RHEL-CentOS 需先安装依赖:sudo yum install -y yum-utils 安装开始: ...

  7. Netty心跳简单Demo

    前面简单地了解了一下IdleStateHandler,我们现在写一个简单的心跳demo: 1)服务器端每隔5秒检测服务器端的读超时,如果5秒没有接受到客户端的写请求,也就说服务器端5秒没有收到读事件, ...

  8. [转] C#调用外部DLL

    原文地址 每种编程语言调用DLL的方法都不尽相同,在此只对用C#调用DLL的方法进行介绍.首先,您需要了解什么是托管,什么是非托管.一般可以认为:非托管代码主要是基于win 32平台开发的DLL,ac ...

  9. delphi 选择文件夹,路径选择,浏览文件夹

    选择文件夹,路径选择, 文件夹 资源管理器 推荐  SelectDirectory http://docwiki.embarcadero.com/Libraries/Seattle/en/Vcl.Fi ...

  10. Java ArrayList的不同排序方法

    本文由 ImportNew - 温布利往事 翻译自 dzone.欢迎加入翻译小组.转载请见文末要求. 由于其功能性和灵活性,ArrayList是 Java 集合框架中使用最为普遍的集合类之一.Arra ...