23种设计模式之---备忘录模式

article/2025/11/11 15:34:53

前言

网上搜索备忘录设计模式,基本上均是在一个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


http://chatgpt.dhexx.cn/article/bT76sLEi.shtml

相关文章

备忘录模式介绍

备忘录模式介绍 一、基本介绍二、代码实现三、UML类图四、备忘录模式小结其他设计模式 一、基本介绍 备忘录模式(Memento Pattern)属于行为型模式,是指在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外…

设计模式 | 备忘录模式及典型应用

本文的主要内容: 介绍备忘录模式示例备忘录模式总结 备忘录模式 备忘录模式经常可以遇到,譬如下面这些场景: 浏览器回退:浏览器一般有浏览记录,当我们在一个网页上点击几次链接之后,可在左上角点击左箭头…

设计模式之备忘录模式

一、备忘录模式 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。 原发器(Originator)角色:原发器根据需要决定将自己的哪些内部状态保存到备忘录中,并可以使…

备忘录模式(Java)

备忘录模式(Java) 下面是关于我所写的所有设计模式代码(还是建议自己手打或者想一个别的例子练习一次) (https://github.com/lihang212010/DesignPatterns-/tree/master/designpatterns/src) 先来张百度的UML 下面是我例子的U…

撤销功能的实现——备忘录模式(二)

21.2 备忘录模式概述 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销(Undo)操作&#xff0…

18-备忘录模式

文章目录 游戏角色状态恢复问题备忘录模式基本介绍备忘录模式解决游戏角色状态回复问题备忘录模式的注意事项和细节 游戏角色状态恢复问题 游戏鱼色有攻击力和防御力,在大战 Boss 前保存自身的状态(攻击力和防御力),当大战 Boss …

详解设计模式:备忘录模式

详解设计模式:备忘录模式 备忘录模式(Memento Pattern)也被称为快照模式(Snapshot Pattern)、Token 模式(Token Pattern),是在 GoF 23 种设计模式中定义了的行为型模式。 备忘录模式…

JAVA设计模式--备忘录模式

目录 一、什么是备忘录模式 二、备忘录模式的结构 三、备忘录模式的适用性 四、备忘录模式的实现 五、备忘录模式的优缺点 六、总结 一、什么是备忘录模式 备忘录(Memento)模式又叫作快照(Snapshot)模式或Token模式,是一种对象的行为模式。在备忘录模式里&am…

设计模式之备忘录模式(C++)

作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 一、备忘录模式是什么? 备忘录模式是一种行为型的软件设计模式,在不破坏封装的前提下,获取一个…

什么是备忘录模式?

一、定义 备忘录模式又称快照模式,或者令牌模式。是指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态,属于行为型模式。 二、通用写法及其uml 发起人角色&a…

行为型模式——备忘录模式(Memento Pattern)

文章目录 备忘录模式(Memento Pattern)什么是备忘录模式?UML角色应用使用模板 为什么要使用备忘录模式?优点:缺点: 怎样使用备忘录模式?在JDK中的使用 备忘录模式(Memento Pattern&a…

备忘录模式

一、备忘录模式 1、定义 备忘录模式(Memento Pattern)又称作快照模式(Snapshot Pattern),指在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象恢复…

设计模式系列----备忘录模式

一、什么是备忘录模式 备忘录这个词汇大家应该都不陌生,我就经常使用备忘录来记录一些比较重要的或者容易遗忘的信息,与之相关的最常见的应用有许多,比如游戏存档,我们玩游戏的时候肯定有存档功能,旨在下一次登录游戏时…

基于MIMO讲解信道估计基本原理

为什么要进行信道估计? 信号在通过信道传输的时候,会受到信道中种种因素产生的噪声以及可能发生的多径效应,弄清信号经过的信道的特性,表征信道的技术/过程称为信道估计(Channel Estimation)。 注&#xf…

m基于深度学习的OFDM信道估计和均衡算法误码率matlab仿真,对比了LS,MMSE以及LMMSE等传统的信道估计算法

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 随着无线通信的快速发展,5G正逐渐成长为支撑全社会各行业运作的大型基础性互联网络,其服务范围的大幅扩展对底层技术提出了诸多挑战,尤其是作为物理层关键技术之一的正交频分复用(Orthogonal Fre…

IRS的信道估计基础代码

一、 智能反射平面(intelligent reflecting surfaces)是一种被动反射表面,其具有的特性是可控制反射信号的相位。 明确IRS是可控制反射信号的相位,所以以单个智能反射单元为例,该单元可调信号的参数可表示为​&#xf…

信道估计算法

目前我所涉及的是短波宽带无线信道下的接收端的处理,包括捕获、同步、信道估计及信道均衡,还有译码。百度百科里是这样解释这种信道的:短波通信发射电波要经电离层的反射才能到达接收设备,通信距离较远,是远程通信的主…

信道估计之LS算法

信道估计之LS算法 前言LS信道估计的原理总结 前言 信道估计是通信系统接收机的重要功能模块,主要是用来估计信号所经历信道的冲击响应,并用于后续的信道均衡处理,以便消除多径信号混叠造成的ISI。 信道估计的方法有很多种,…

信道估计之LMMSE估计

之前的内容讲到了MMSE信道估计,并推导了基于MMSE优化准则的估计结果,该方法是对LS信道估计的进一步优化,适用于低信噪比场合,但由于其计算复杂,所以并不实用。因此又有了LMMSE信道估计方法,相对于MMSE估计&…

详解信道估计的发展与最新研究进展(MIMO)

目录 一. MIMO信道估计的重要性 二. 最经典的两种信道估计方法 2.1 最小二乘信道估计(LS) 2.2 最小均方误差信道估计(MMSE) 三. 优化传统的MIMO信道估计技术 四. 介绍压缩感知技术 五. 基于压缩感知的MIMO信道估计 5.1 压缩感知怎么用在MIMO信道估计 5.2 改进压缩感知…