备忘录模式

引言

        当我们和朋友下棋的时候,我们很多情况下会发现下了一步臭棋,这时候就会和朋友开玩笑要悔棋,即撤回刚刚下的一步棋。在程序中,很多时候也会出错,我们也希望程序可以恢复出错前的状态,这就需要备忘录模式来实现。

1.概念

        备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。它是一种对象行为型模式,其别名为Token。

2.模式结构

3.模式分析

        Originator:原发器,是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。核心代码如下:

public class Originator {private String state;public Originator() {}// 创建一个备忘录对象public Memento createMemento() {return new Memento(this);}// 根据备忘录对象恢复原发器状态public void restoreMemento(Memento m) {state = m.state;}public void setState(String state) {this.state = state;}public String getState() {return this.state;}}

        Memento:备忘录,存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。核心代码如下:

class Memento{private String state;public Memento(Originator o) {state = o.getState();}public void setState(String state) {this.state = state;}public String getState() {return this.state;}}

        Caretaker:负责人,负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须知道对象的实现细节。核心代码如下:

public class Caretaker {private Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}

4.具体实例分析

        ChessOriginator:象棋原发器,定义象棋的类型和位置属性,以及相关的构造方法、Getter和Setter方法,原发器需要包含创建备忘录的方法和状态恢复方法。具体代码如下:

//象棋原生类public class ChessOriginator {private String label;private int x;private int y;public ChessOriginator(String label, int x, int y) {this.label = label;this.x = x;this.y = y;}public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}// 创建一个备忘录对象public ChessMemento createMemento() {return new ChessMemento(this.label,this.x,this.y);}// 根据备忘录对象恢复原发器状态public void restoreMemento(ChessMemento chessMemento) {this.label = chessMemento.getLabel();this.x = chessMemento.getX();this.y = chessMemento.getY();}@Overridepublic String toString() {return "棋子:" + label + " 当前位置:(" + x + ", " + y + ")";}}

        ChessMemento:象棋备忘录,负责记录象棋的某时刻状态。具体代码如下:

//象棋备忘录class ChessMemento{private String label;private int x;private int y;public ChessMemento(String label, int x, int y) {this.label = label;this.x = x;this.y = y;}public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}}

        MementoCaretaker:备忘录管理类,负责管理象棋备忘录,比如获得上一时刻的象棋状态和保存上一时刻的象棋状态。具体代码如下:

//负责人:象棋备忘录管理类public class MementoCaretaker {private ChessMemento chessMemento;public ChessMemento getMemento() {return chessMemento;}public void setMemento(ChessMemento chessMemento) {this.chessMemento = chessMemento;}}Client:客户端,模拟象棋悔棋。具体代码如下:public class Client {public static void main(String[] args) {MementoCaretaker mementoCaretaker = new MementoCaretaker();ChessOriginator chessOriginator = new ChessOriginator("炮",2,2);System.out.println(chessOriginator);mementoCaretaker.setMemento(chessOriginator.createMemento());//保存上一步状态chessOriginator.setX(4);System.out.println(chessOriginator);//悔棋System.out.println("求求你让我悔棋吧!!!");chessOriginator.restoreMemento(mementoCaretaker.getMemento());System.out.println(chessOriginator);}}

        运行代码,结果如下:

5.优缺点

        主要优点如下:

        (1)它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。

        (2)备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

        主要缺点如下:

        (1)资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。

6.适用情况

        (1)保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时它能够恢复到先前的状态,实现撤销操作。

        (2)防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14425.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Element UI 表单源码原理

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

使用deepseek快速创作ppt

目录 1.在DeekSeek生成PPT脚本2.打开Kimi3.最终效果 DeepSeek作为目前最强大模型,其推理能力炸裂,但是DeepSeek官方没有提供生成PPT功能,如果让DeepSeek做PPT呢? 有个途径:在DeepSeek让其深度思考做出PPT脚本&#xf…

深入理解小波变换:信号处理的强大工具

引言 在科学与工程领域,信号处理一直是关键环节,傅里叶变换与小波变换作为重要的分析工具,在其中发挥着重要作用。本文将深入探讨小波变换,阐述其原理、优势以及与傅里叶变换的对比,并通过具体案例展示其应用价值。 一…

Kafka 入门与实战

一、Kafka 基础 1.1 创建topic kafka-topics.bat --bootstrap-server localhost:9092 --topic test --create 1.2 查看消费者偏移量位置 kafka-consumer-groups.bat --bootstrap-server localhost:9092 --describe --group test 1.3 消息的生产与发送 #生产者 kafka-cons…

WPS如何接入DeepSeek(通过第三方工具)

WPS如何接入DeepSeek 一、下载并安装OfficeAI插件二、配置OfficeAI插件三、使用DeepSeek功能 本文介绍如何通过 WPS 的第三方工具调用 DeepSeek 大模型,实现自动化文本扩写、校对和翻译等功能。 一、下载并安装OfficeAI插件 1、访问OfficeAI插件下载地址&#xff…

Day 32 卡玛笔记

这是基于代码随想录的每日打卡 455. 分发饼干 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸&#xff…

[渗透测试]热门搜索引擎推荐— — shodan篇

[渗透测试]热门搜索引擎推荐— — shodan篇 免责声明:本文仅用于分享渗透测试工具,大家使用时,一定需要遵守相关法律法规。 除了shodan,还有很多其他热门的,比如:fofa、奇安信的鹰图、钟馗之眼等&#xff0…

BUU30 [网鼎杯 2018]Fakebook1

是一个登录界面&#xff0c;我们先注册一个试试&#xff1a; 用dirsearch扫描出来robots.txt&#xff0c;也发现了flag.php&#xff0c;并下载user.php.bak 源代码内容&#xff1a; <?phpclass UserInfo {public $name "";public $age 0;public $blog &quo…

索引失效的场景

chatGpt 7. 使用 DISTINCT 或 GROUP BY 当查询中涉及 DISTINCT 或 GROUP BY 时&#xff0c;如果查询没有合适的索引支持&#xff0c;可能会导致性能问题&#xff0c;虽然不完全是索引失效&#xff0c;但会影响查询效率。 sql SELECT DISTINCT department_id FROM employees;…

3D数字化营销:重塑家居电商新生态

随着电商的蓬勃发展&#xff0c;网上订购家具已成为众多消费者的首选。然而&#xff0c;线上选购家具的诸多挑战&#xff0c;如风格不匹配、尺寸不合适、定制效果不如预期以及退换货不便等&#xff0c;一直困扰着消费者。为解决这些问题&#xff0c;家居行业急需一种全新的展示…

论文阅读--LlaVA

数据 使用GPT-4&#xff0c;根据现有的图片对数据&#xff08;image-pair data&#xff09;收集指令跟随数据。作者团队收集了158,000个独特的语言-图像指令遵循样本&#xff0c;其中包括58,000个对话样本、23,000个详细描述样本和77,000个复杂推理样本 以图像描述为例&#x…

【R语言】apply函数族

在R语言中使用循环操作时是使用自身来实现的&#xff0c;效率较低。所以R语言有一个符合其统计语言出身的特点&#xff1a;向量化。R语言中的向量化运用了底层的C语言&#xff0c;而C语言的效率比高层的R语言的效率高。 apply函数族主要是为了解决数据向量化运算的问题&#x…

归一化与伪彩:LabVIEW图像处理的区别

在LabVIEW的图像处理领域&#xff0c;归一化&#xff08;Normalization&#xff09;和伪彩&#xff08;Pseudo-coloring&#xff09;是两个不同的概念&#xff0c;虽然它们都涉及图像像素值的调整&#xff0c;但目的和实现方式截然不同。归一化用于调整像素值的范围&#xff0c…

【3分钟极速部署】在本地快速部署deepseek

第一步&#xff0c;找到网站&#xff0c;下载&#xff1a; 首先找到Ollama &#xff0c; 根据自己的电脑下载对应的版本 。 我个人用的是Windows 我就先尝试用Windows版本了 &#xff0c;文件不是很大&#xff0c;下载也比较的快 第二部就是安装了 &#xff1a; 安装完成后提示…

论文阅读:MGMAE : Motion Guided Masking for Video Masked Autoencoding

MGMAE:Motion Guided Masking for Video Masked Autoencoding Abstract 掩蔽自编码&#xff08;Masked Autoencoding&#xff09;在自监督视频表示学习中展现了出色的表现。时间冗余导致了VideoMAE中高掩蔽比率和定制的掩蔽策略。本文旨在通过引入运动引导掩蔽策略&#xff0…

【Ai】--- 可视化 DeepSeek-r1 接入 Chatbox(超详细)

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【Ai】--- 可视化 DeepSeek-r1 接入 Chat…

P1049 装箱问题(dp)

#include<bits/stdc.h> using namespace std;int main() {int v,n;cin>>v>>n;int a[30];int dp[20005];for(int i0;i<n;i){cin>>a[i];}memset(dp,0,sizeof(dp));// 设置所有元素为0&#xff0c;表示最大体积为0for(int i0;i<n;i){for(int jv;j&…

程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<7>

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 今天我们一起来学习转移表&#xff0c;回调函数&#xff0c;qsort… 目录 一、转移表1.1 定义与原理1.3…

声明式导航,编程式导航,导航传参,下拉刷新

1.页面导航 1.声明式导航 1.1跳转到tabBar页面 1.2跳转到非tabBar页面 1.2后退导航 、 2.编程式导航 2.1跳转到tabBar页面 2.1跳转到非tabBar页面 2.3后退导航 3.导航传参 3.1声名式导航传参 3.2编程式导航传参 3.3在onLoad中接受参数 4.下拉刷新 4.1回顾下拉刷新…

C++ Primer 递增和递减运算符

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…