前言

网上搜索备忘录设计模式,基本上均是在一个GoF,基础上衍生下来的。为了避免重复造轮子,这里会结合网上demo,和自己理解进行总结

定义:备忘录(Memento)模式又称标记(Token)模式。GOF给备忘录模式的定义为:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

角色分类:

 1) 备忘录(Memento)角色:备忘录角色存储“备忘发起角色”的内部状态。“备忘发起角色”根据需要决定备忘录角色存储“备忘发起角色”的哪些内部状态。为了防止“备忘发起角色”以外的其他对象访问备忘录。备忘录实际上有两个接口,“备忘录管理者角色”只能看到备忘录提供的窄接口——对于备忘录角色中存放的属性是不可见的。“备忘发起角色”则能够看到一个宽接口——能够得到自己放入备忘录角色中属性。

  2) 备忘发起(Originator)角色:“备忘发起角色”创建一个备忘录,用以记录当前时刻它的内部状态。在需要时使用备忘录恢复内部状态。

  3) 备忘录管理者(Caretaker)角色:负责保存好备忘录。不能对备忘录的内容进行操作或检查。

角色职责:

发起人角色
  发起人角色有如下责任:
  (1)创建一个含有当前的内部状态的备忘录对象。
  (2)使用备忘录对象存储其内部状态。
负责人角色
  负责人角色有如下责任:
  (1)负责保存备忘录对象。
(2)不检查备忘录对象的内容。

分类:

1.”白箱”备忘录模式的实现

2.“黑箱”备忘录模式的实现

3.“多重”检查点

4.”自述历史”模式

三、举例

  按照定义中的要求,备忘录角色要保持完整的封装。最好的情况便是:备忘录角色只应该暴露操作内部存储属性的的接口给“备忘发起角色”。而对于其他角色则是不可见的。GOF在书中以C++为例进行了探讨。但是在Java中没有提供类似于C++中友元的概念。在Java中怎样才能保持备忘录角色的封装呢?

下面对三种在Java中可保存封装的方法进行探讨。

  第一种就是采用两个不同的接口类来限制访问权限。这两个接口类中,一个提供比较完备的操作状态的方法,我们称它为宽接口;而另一个则可以只是一个标示,我们称它为窄接口。备忘录角色要实现这两个接口类。这样对于“备忘发起角色”采用宽接口进行访问,而对于其他的角色或者对象则采用窄接口进行访问。

  这种实现比较简单,但是需要人为的进行规范约束——而这往往是没有力度的。

  第二种方法便很好的解决了第一种的缺陷:采用内部类来控制访问权限。将备忘录角色作为“备忘发起角色”的一个私有内部类。好处我不详细解释了,看看代码吧就明白了。下面的代码是一个完整的备忘录模式的教学程序。它便采用了第二种方法来实现备忘录模式。

  还有一点值得指出的是,在下面的代码中,对于客户程序来说“备忘录管理者角色”是不可见的,这样简化了客户程序使用备忘录模式的难度。下面采用“备忘发起角色”来调用访问“备忘录管理者角色”,也可以参考门面模式在客户程序与备忘录角色之间添加一个门面角色。

第三种方式是不太推荐使用的:使用clone方法来简化备忘录模式。由于Java提供了clone机制,这使得复制一个对象变得轻松起来。使用了clone机制的备忘录模式,备忘录角色基本可以省略了,而且可以很好的保持对象的封装。但是在为你的类实现clone方法时要慎重啊。

  在上面的教学代码中,我们简单的模拟了备忘录模式的整个流程。在实际应用中,我们往往需要保存大量“备忘发起角色”的历史状态。这时就要对我们的“备忘录管理者角色”进行改造,最简单的方式就是采用容器来按照顺序存放备忘录角色。这样就可以很好的实现undo、redo功能了。

“白箱”备忘录模式的实现

备忘录角色对任何对象都提供一个接口,即宽接口,备忘录角色的内部所存储的状态就对所有对象公开。因此这个实现又叫做“白箱实现”。
  “白箱”实现将发起人角色的状态存储在一个大家都看得到的地方,因此是破坏封装性的。但是通过程序员自律,同样可以在一定程度上实现模式的大部分用意。因此白箱实现仍然是有意义的。
  下面给出一个示意性的“白箱实现”。

demo 入口

package com.wc.momoto;/*** 类似白箱备忘录模式* @author weichyang**/
public class Client {/*** 客户端* * @param args*/public static void main(String[] args) {int state = 3;Originator originator = new Originator();Caretaker caretaker = new Caretaker();originator.setState(state);/*** 创建备忘录对象的 缓存起来*/caretaker.saveMemento(originator.creatMementoObject());/** 进行设置重新还原*/originator.setState(5);System.out.println("发起人更改状态:" + originator.getState());originator.restoreMemento(caretaker.retrieveMemento());}}

管理者,负责发起者的管理

package com.wc.momoto;/*** 管理者 负责管理Caretaker* * @author weichyang* */
public class Caretaker {private Memento memento;/*** 备忘录的取值方法*/public Memento retrieveMemento() {return this.memento;}/*** 备忘录的赋值方法*/public void saveMemento(Memento memento) {this.memento = memento;}}

备忘录,对发起者进行缓存的类

package com.wc.momoto;/*** 备忘录* * @author weichyang* */
public class Memento {private int state;public Memento() {super();}public Memento(int state) {this.state = state;System.out.println("备忘录 当前保存 状态:" + state);}public int getState() {return state;}public void setState(int state) {this.state = state;}}

发起者,负责备忘录的创建,修改,恢复

package com.wc.momoto;/*** 发起者* * @author weichyang* */
public class Originator {private int state = 0;Caretaker caretaker = new Caretaker();public Memento creatMementoObject() {return new Memento(state);}/*** 将发起人恢复到备忘录对象所记载的状态*/public void restoreMemento(Memento memento) {this.state = memento.getState();System.out.println("恢复 备忘录 状态:" + state);}public int getState() {return state;}public void setState(int state) {this.state = state;}}

“黑箱”备忘录模式的实现

  备忘录角色对发起人(Originator)角色对象提供一个宽接口,而为其他对象提供一个窄接口。这样的实现叫做“黑箱实现”。
  在JAVA语言中,实现双重接口的办法就是将备忘录角色类设计成发起人角色类的内部成员类。
  将Memento设成Originator类的内部类,从而将Memento对象封装在Originator里面;在外部提供一个标识接口 MementoIF给Caretaker以及其他对象。这样,Originator类看到的是Menmento的所有接口,而Caretaker以及其他 对象看到的仅仅是标识接口MementoIF所暴露出来的接口。

package com.wc.momoto.black;/*** 类似黑箱备忘录模式* * @author weichyang* */
public class Client {/*** 客户端* * @param args*/public static void main(String[] args) {int state = 3;Originator originator = new Originator();Caretaker caretaker = new Caretaker();originator.setState(state);/*** 创建备忘录对象的 缓存起来*/caretaker.saveMemento(originator.creatMementoObject());/** 进行设置重新还原*/originator.setState(5);System.out.println(" 黑箱发起人更改状态:" + originator.getState());originator.restoreMemento(caretaker.retrieveMemento());}}
package com.wc.momoto.black;public interface MemotoIF {}
package com.wc.momoto.black;/*** 发起者*  内部类如何拿到外部类的引用   https://zhidao.baidu.com/question/513464853.html*  已经外部类如何访问内部类中的成员* @author weichyang* */
public class Originator {private int state = 0;Caretaker caretaker = new Caretaker();public Memento creatMementoObject() {return new Memento(state);}/*** 将发起人恢复到备忘录对象所记载的状态*/public void restoreMemento(MemotoIF momIf) {this.setState(((Memento) momIf).getState());System.out.println("黑箱恢复 备忘录 状态:" + state);}public int getState() {return state;}public void setState(int state) {this.state = state;}private class Memento implements MemotoIF {private int state;public Memento(int state) {this.state = state;System.out.println("黑箱备忘录 当前保存 状态:" + state);}public int getState() {return state;}public void setState(int state) {this.state = state;}}}
package com.wc.momoto.black;/*** 管理者 负责管理Caretaker* * @author weichyang* */
public class Caretaker {private MemotoIF memento;/*** 备忘录的取值方法*/public MemotoIF retrieveMemento() {return this.memento;}/*** 备忘录的赋值方法*/public void saveMemento(MemotoIF memento) {this.memento = memento;}}

多重检查点

  前面所给出的白箱和黑箱的示意性实现都是只存储一个状态的简单实现,也可以叫做只有一个检查点。常见的系统往往需要存储不止一个状态,而是需要存储多个状态,或者叫做有多个检查点。
  备忘录模式可以将发起人对象的状态存储到备忘录对象里面,备忘录模式可以将发起人对象恢复到备忘录对象所存储的某一个检查点上。

4.”自述历史”模式

  所谓“自述历史”模式(History-On-Self Pattern)实际上就是备忘录模式的一个变种。在备忘录模式中,发起人(Originator)角色、负责人(Caretaker)角色和备忘录 (Memento)角色都是独立的角色。虽然在实现上备忘录类可以成为发起人类的内部成员类,但是备忘录类仍然保持作为一个角色的独立意义。在“自述历 史”模式里面,发起人角色自己兼任负责人角色。
  
  

个人比较推崇黑箱模式。而且很多开源的同样使用黑箱模式进行开发。关于多重检查点,只是在备忘录保存一个状态的基础上增加了多个状态,写法并没有变化。而自述历史,同样是简化版的黑箱。再次不在贴代码,有刨根问底的可以看下面具体的引用 blog:进行学习

Demo:下载地址: http://pan.baidu.com/s/1ciqUmy

引用地址:

云栖blog https://yq.aliyun.com/articles/14312
备忘录模式 : http://www.dedecms.com/knowledge/program/jsp-java/2012/0824/13291.html
Java 备忘录模式: http://blog.csdn.net/jianguo_liao19840726/article/details/6445282

23种设计模式之---备忘录模式相关推荐

  1. 在王者荣耀角度下分析面向对象程序设计B中23种设计模式之备忘录模式

    · 备忘录模式在王者荣耀中的应用 · 一.简述 在王者荣耀的游戏中,贤者的庇护这件装备设计的初衷是提高容错率,常常出现在游戏后期,玩家通过装备贤者的庇护在危急时刻可以实现复活效果,进而保命. 二.备忘 ...

  2. 23种设计模式之备忘录模式

    备忘录模式的定义 定义: 在不破坏封装性的前提下, 捕获一个对象的内部状态, 并在该对象之外保存这个状态. 这样以后就可将该对象回复到原先保存的状态 通俗的说, 就是记录下类的当前状态, 当需要的时候 ...

  3. 【Go实现】实践GoF的23种设计模式:命令模式

    上一篇:[Go实现]实践GoF的23种设计模式:代理模式 简单的分布式应用系统(示例代码工程):https://github.com/ruanrunxue/Practice-Design-Patter ...

  4. 23种设计模式——装饰者模式

    文章目录 23种设计模式--装饰者模式 1.装饰者模式概述 2.装饰者模式的结构 3.装饰者模式的实现 4.装饰者模式的应用场景 23种设计模式--装饰者模式 1.装饰者模式概述 背景 有些人为了早上 ...

  5. 实践GoF的23种设计模式:建造者模式

    本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:建造者模式>,作者: 元闰子. 简述 在程序设计中,我们会经常遇到一些复杂的对象,其中有很多成员属性,甚至嵌套着多个复杂的对象 ...

  6. 23种设计模式7_代理模式之一静态代理

    23种设计模式7_代理模式之一静态代理 1 基本介绍 代理模式:为其他对象提供一种代理以控制对这个对象的访问 代理模式也叫委托模式,它是一项基本设计技巧.许多其他的模式,如状态模式.策略模式.访问者模 ...

  7. 23种设计模式之命令模式和策略模式的区别

    文章目录 概述 命令模式 策略模式 相同点 总结 概述 命令模式和策略模式确实很相似,只是命令模式多了一个接收者(Receiver)角色.它们虽然同为行为类模式,但是两者的区别还是很明显的.策略模式的 ...

  8. 23种设计模式之代理模式

    文章目录 代理模式的定义与特点 代理模式的结构与实现 模式的结构 模式的实现 代理模式的应用场景 代理模式的应用实例 代理模式的扩展 代理模式分类 静态代理 动态代理 在有些情况下,一个客户不能或者不 ...

  9. 23种设计模式----中介者模式----行为型模式

    中介者模式 1.什么是中介者模式 2.中介者模式的角色 3.例子 3.1 项目结构 3.2 共同实体 3.3 抽象的中介者 3.4 抽象的被中介者 3.5 具体的中介者 3.6 具体的被中介者 3.7 ...

最新文章

  1. ping通网关不能上网_手机、电脑为什么连不上网(断网)?
  2. Xamarin.Forms使用Slider注意问题
  3. linux换源 最最简单
  4. NLP之ASR:语音识别技术(Automatic Speech Recognition)的简介、发展历史、案例应用之详细攻略
  5. 2019年,异质图神经网络领域有哪些值得读的顶会论文?
  6. Just $h$-index HDU - 6278(主席树找区间大于等于k的个数)
  7. “后见之明”是冰冷刻薄的讥讽;这是一种病,得治。
  8. hdu 5233 Gunner II
  9. java exec dir的例子_java.lang.Runtime.exec(String[] cmdarray, String[] envp, File dir)方法实例...
  10. ae万能弹性表达式_干货丨AE表达式知多少?4大常用表示式解决80%难题
  11. SFM(Structure from Motion)一点总结
  12. word参考文献交叉引用
  13. Elasticsearch入门----terms聚合实现搜索热词统计
  14. 台湾J2ME专家王森北京讲座---掌上开发专业研讨
  15. 【硬件篇之电源纹波噪声测试】
  16. python msp_MSP系统使用python语言实现接口自动化
  17. 计算机考研没有科研经历和竞赛,2020考研复试:没有竞赛、科研经历,4个方法教你实现逆袭...
  18. 深度学习简介--PPT
  19. java实现测量到的工程数据
  20. 解决Win10中MSCOMM32.ocx没注册问题

热门文章

  1. 会声会影X10 64位整合光盘V10.1.0.14简体中文版 下载
  2. 三、使用 nc -lk 监听socketTextStream
  3. draft-editor实现粘贴上传图片
  4. 【转】共享经济是临时工的增量市场?
  5. 满意度调查的几种常用方法
  6. Python爬虫 - 爬取豆瓣读书TOP250电子书
  7. 关于EBS中ERP 工作台释放工单时Date的关系和验证
  8. SMPTE ST 2094 and Dynamic Metadata
  9. 今天会用了正则表达式
  10. 汽车电子_EMC测试_CE试验整改