设计模式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.概述 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来 ...
随机推荐
- Window app遇到的问题
Windows下两个应用之间进行UDP通讯,必须要先互相发送过数据,才能收到其他的数据.解决方法: <Capabilities> <Capability Name="int ...
- Druid.io系列(五):查询过程
原文链接: https://blog.csdn.net/njpjsoftdev/article/details/52956194 Druid使用JSON over HTTP 作为底层的查询语言,不过强 ...
- socket通信循环
server-----------------#!/usr/bin/env python # encoding: utf-8 # Date: 2018/6/5 import socket phone ...
- ascii码与二进制码有何区别?
ascii编码和二进制码是两个概念.ASCII主要是为了电脑显示和传输拉丁字母而发明的一套编码,二进制则是为了计算机方便计算.传输数据而使用的一种方法.ASCII(American Standard ...
- hadoop性能测试
一.hadoop自带的性能基准评测工具 (一)TestDFSIO 1.测试写性能 (1)若有必要,先删除历史数据 $hadoop jar /home/hadoop/hadoop/share/hadoo ...
- Windows C盘文件夹介绍及说明
Documents and Settings是什么文件? 答案: 是系统用户设置文件夹,包括各个用户的文档.收藏夹.上网浏览信息.配置文件等. 补:这里面的东西不要随便删除,这保存着所有用户的文档和账 ...
- 19_java之List和Set
01List接口的特点 A:List接口的特点: a:它是一个元素存取有序的集合. 例如,存元素的顺序是11.22.33.那么集合中,元素的存储就是按照11.22.33的顺序完成的). b:它是一 ...
- 用CSS制作小三角提示符号
今天在项目中遇到了如下图的切图要求. 对,重点就是那个小三角提示符号. html 结构如下 <div class="wrap"> <div class=" ...
- ajax 回调函数
回调函数 如果要处理$.ajax()得到的数据,则需要使用回调函数.beforeSend.error.dataFilter.success.complete. beforeSend 在发送请求之前调用 ...
- HTML 空白
HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...