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

article/2025/11/10 19:00:08

目录

一、什么是备忘录模式

二、备忘录模式的结构

三、备忘录模式的适用性

四、备忘录模式的实现

五、备忘录模式的优缺点

六、总结


一、什么是备忘录模式

备忘录(Memento)模式又叫作快照(Snapshot)模式或Token模式,是一种对象的行为模式。在备忘录模式里,一个备忘录是一个对象,它存储另一个对象(备忘录的原发器)在某个瞬间的内部状态。备忘的目的就是为了以后在需要的时候,可以将原发器对象的状态恢复(undo/rollback)到备忘录所保存的状态。

备忘录的本质:保存和恢复状态

设计意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复(undo/rollback)到原先保存的状态了。  

二、备忘录模式的结构

备忘录模式涉及的角色及其职责如下:

原发器(Originator)角色:原发器根据需要决定将自己的哪些内部状态保存到备忘录中,并可以使用备忘录来恢复内部状态。
           备忘录(Memento)角色:负责存储原发器对象的内部状态,但是具体需要存储哪些状态是由原发器对象来决定的。另外备忘录应该只能由原发器对象来访问它内部的数据,原发器外部的对象不应该访问到备忘录对象的内部数据。
           为了控制对备忘录对象的访问,备忘录模式中出现了窄接口和宽接口的概念。
           • 窄接口:管理者只能看到备忘录的窄接口,窄接口的实现中通常没有任何的方法,只是一个类型标识。窄接口使得管理者只能将备忘录传递给其他对象。
           • 宽接口:原发器能够看到备忘录的宽接口,从而可以从备忘录中获取到所需的数据,来将自己恢复到备忘录中所保存的状态。理想情况是:只允许生成备忘录的原发器来访问该备忘录的内部状态,通常实现成为原发器内的一个私有内部类。
           管理者(Caretaker)角色:备忘录管理者,或者称为备忘录负责人。主要负责保存好备忘录对象,但是不能对备忘录对象的内容进行操作或检查。

备忘录模式结构示意源代码如下:

先来看看备忘录窄接口的定义。 

/*** 备忘录的窄接口,没有任何方法定义*/
public interface Memento {
}

再看看原发器角色,它里面会有备忘录对象的实现,此处将真正的备忘录对象当作原发器对象的一个私有内部类来实现。示例代码如下:  

public class Originator {/*** 示意,表示原发器的状态*/private String state = "";/*** 创建备忘录,保存原发器的状态* * @return 创建好的备忘录对象*/public Memento createMemento() {return new MementoImpl(state);}/*** 将原发器恢复到备忘录中保存的状态* * @param 保存有原发器状态的备忘录对象*/public void recoverFromMemento(Memento memento) {MementoImpl mementoImpl = (MementoImpl) memento;this.state = mementoImpl.getState();}public String getState() {return state;}public void setState(String state) {this.state = state;}/*** 真正的备忘录对象,实现了备忘录窄接口 实现成私有的内部类,不让外部访问*/private static class MementoImpl implements Memento {/*** 示意,表示需要保存的状态*/private String state = "";public MementoImpl(String state) {super();this.state = state;}public String getState() {return state;}}}

接下来是备忘录管理者的示例代码。  

public class Caretaker {/*** 记录被保存的备忘录对象*/private Memento memento = null;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}

创建一个客户端来测试一下,示例代码如下。  

public class Client {public static void main(String[] args) {// 创建一个原发器Originator o = new Originator();// 设置其初始状态o.setState("state 0");// 打印原发器当前的状态System.out.println("原发器的初始状态:" + o.getState());// 将原发器当前的状态保存到备忘录中Memento memento = o.createMemento();// 创建一个管理者Caretaker c = new Caretaker();// 将创建好的备忘录交给管理者进行管理c.setMemento(memento);// 改变原发器的状态o.setState("state 1");// 打印原发器当前的状态System.out.println("原发器改變后状态:" + o.getState());// 将原发器状态恢复到备忘录保存的状态o.recoverFromMemento(c.getMemento());// 再次打印原发器当前的状态System.out.println("原发器恢復后状态:" + o.getState());}
}

运行程序打印结果如下:  

原发器的初始状态:state 0
原发器改變后状态:state 1
原发器恢復后状态:state 0

在备忘录模式中,备忘录对象通常用来记录原发器中需要保存的内部状态,为了不破坏原发器对象的封装性,一般只让原发器自己来操作它的备忘录对象。为了保证这一点,通常会把备忘录对象作为原发器对象的内部类来实现,而且实现成私有的,这样就断了外部来访问这个备忘录对象的途径。

把备忘录对象设计成为一个私有的内部类,外部只能通过备忘录对象的窄接口来获取备忘录对象,而这个接口没有任何方法,仅仅起到了一个标识对象类型的作用,从而保证内部的数据不会被外部获取或是操作,保证了原发器对象的封装性,也就不再暴露原发器对象在内部结构了。  

三、备忘录模式的适用性

在以下条件下可以考虑使用备忘录模式:
           • 如果必须保存一个对象在某一个时刻的全部或部分状态,方便在以后需要的时候,可以把该对象恢复到先前的状态。
           • 如果需要保存一个对象的内部状态,但是如果用接口来让其它对象直接得到这些需要保存的状态,将会暴露对象的实现细节并破坏对象的封装性,这时可以使用备忘录模式,把备忘录对象实现成为原发器对象的私有内部类,从而保证只有原发器对象才能访问该备忘录对象。这样既保存了需要保存的状态,又不会暴露原发器对象的内部实现细节。  

四、备忘录模式的实现

增量存储:
           如果需要频繁地创建备忘录对象,而且创建和应用备忘录对象来恢复状态的顺序是可控的,那么可以让备忘录进行增量存储,也就是备忘录可以仅仅存储原发器内部相对于上一次存储状态后的增量改变。
           结合原型模式:
           在原发器对象创建备忘录对象的时候,如果原发器对象中全部或者大部分的状态都需要保存,一个简洁的方式就是直接克隆一个原发器对象。
           离线存储:
           备忘录的数据可以实现成为离线存储,除了存储在内存中,还可以把备忘录数据存储到文件中、XML中、数据库中,从而支持跨越会话的备份和恢复功能。  

五、备忘录模式的优缺点

使用备忘录模式的优点:

(1)更好的封装性
           备忘录模式通过使用备忘录对象,来封装原发器对象的内部状态,虽然这个对象是保存在原发器对象的外部,但是由于备忘录对象的窄接口并不提供任何方法。这样有效地保证了对原发器对象内部状态的封装,不把原发器对象的内部实现细节暴露给外部。
           (2)简化了原发器
           在备忘录模式中,原发器不再需要管理和保存其内部状态的一个个版本,而是交由管理者或客户端对这些状态的版本进行管理,从而让原发器对象得到简化。
           (3)窄接口和宽接口
           备忘录模式,通过引入窄接口和宽接口,使得不同的地方,对备忘录对象的访问是不一样的。窄接口保证了只有原发器才可以访问备忘录对象存储的状态。

使用备忘录模式的缺点:

(1)标准的备忘录模式的实现机制是依靠缓存来实现的,因此,当需要备忘的数据量较大时,或者是存储的备忘录对象数据量不大但是数量很多的时候,或者是用户很频繁地创建备忘录对象的时候,这些都会导致非常大的开销。
           (2)管理者负责维护备忘录,然而,管理者并不知道备忘录中有多少个状态。因此当存储备忘录时,一个本来很小的管理者,可能会产生大量的存储开销。 

六、总结

备忘录模式的功能,首先是在不破坏封装性的前提下,捕获一个对象的内部状态。这里要注意两点,一个是不破坏封装性,也就是对象不能暴露它不应该暴露的细节;另外一个是捕获的是对象的内部状态,而且通常还是运行期间某个时刻对象的内部状态。
           之所以要捕获这些内部状态,是为了在以后的某个时候,可以将该对象的状态恢复到备忘录所保存的状态,这才是备忘录真正的目的。前面保存状态就是为了后面恢复,虽然不是一定要恢复,但是目的是为了恢复。
           在备忘录模式中,备忘录对象通常用来记录原发器中需要保存的内部状态,为了不破坏原发器对象的封装性,一般只让原发器自己来操作它的备忘录对象。为了保证这一点,通常会把备忘录对象作为原发器对象的内部类来实现,而且实现成私有的,这样就断了外部来访问这个备忘录对象的途径。  


http://chatgpt.dhexx.cn/article/3re5n6K9.shtml

相关文章

设计模式之备忘录模式(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 改进压缩感知…

c语言差分qpsk编码信道估计 pudn,请教一下OFDM中的信道估计

在AWGN信道中没有多径 这样信道估计和均衡对结果的影响有多少dB呢? 进行了一下仿真,没有加信道编码,用LS信道估计和一阶均衡 附件是仿真的误码率对比图,从图中可以看出均衡似乎对误码率有3dB的恶化 图中横轴是SNR 其中没有均衡的曲…

m基于机器学习MLP的OFDM信道估计误码率matlab仿真,对比LS和MMSE两种信道估计算法

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 信道估计器是接收机一个很重要的组成部分。在OFDM系统中,信道估计器的设计上要有两个问题:一是导频信息的选择,由于无线信道的时变特性,需要接收机不断对信道进…

OFDM通信系统的LS信道估计均衡算法matlab仿真

目录 一、理论基础 二、核心程序 三、仿真结论 一、理论基础 OFDM主要思想是:将信道分成若干正交子信道,将高速数据信号转换成并行的低速子数据流,调制到在每个子信道上进行传输。正交信号可以通过在接收端采用相关技术来分开,…

MIMOl信道估计基本原理

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

基于导频的信道估计实现

目录 零、前言 一、为什么要信道估计 二、导频的概念 (1)为什么要有导频 (2)导频在信道估计中作用 (3)关于导频序列的补充 三、最小二乘法估计 (1)LS信道估计算法分析 &…

DFT信道估计步骤及实例

在OFDM系统中,基于DFT的信道估计算法也经常被使用。DFT信道估计主要有以下几个步骤: (1)在实载波导频处,利用已知导频符号,使用LS信道估计算法计算得到实载波导频处信道频域响应:(原理详见此处) H ^ P _ A…

【OMP信道估计】基于OMP压缩感知的信道估计算法的MATLAB仿真

1.软件版本 MATLAB2021a2.本算法理论知识 3.核心代码 clc; clear; close all; warning off; addpath func\CYC 20; for ij 1:CYCijCYC 20;RandStream.setDefaultStream(RandStream(mt19937ar,seed,ij));Len 8;Nc 64*Len;%子载波数T …

OFDM学习笔记(四)(信道估计简介)

目录 1.基本介绍2.慢衰落信道下的信道估计算法2.1 基于DFT的信道估计算法2.2 基于SVD的信道估计算法2.3 基于滤波器的信道估计算法2.4 最大似然估计算法 相干解调在实际中应用的比差分解调多很多。而信道估计作为相干解调的主要技术就尤为重要。 信道估计器是接收机一个很重要…