当前位置: 首页 > news >正文

备忘录模式-撤销功能的实现

 在idea写代码的过程中,会经常用到一个快捷键——“crtl + z”,即撤销功能。“备忘录模式”则为撤销功能提供了一个设计方案。

1 备忘录模式

备忘录模式提供一种状态恢复机制。在不破坏封装的前提下,捕获对象内部状态并在该对象之外保存这个状态。可以在以后将对象恢复到原先保存的状态。

图 备忘录UML

Originator:原发器,一个需要保存内部状态的普通类,可以创建一个备忘录,也可通过备忘录来恢复其在某个时候的状态。

Memento:备忘录,存储原发器的内部状态。除了原发器本身及管理者类外,备忘录不能直接供其他类使用。

CareTaker:管理者,负责保存备忘录,但不能对备忘录内容进行操作或检查,无须知道备忘录的细节。

@Data
public class IdeaCodeOriginator {private String code;private Integer position;public IdeaCodeOriginator(String code, Integer position) {this.code = code;this.position = position;}public void restoreMemento(IdeaCodeMemento memento) {this.code = memento.getCode();this.position = memento.getPosition();}public IdeaCodeMemento createMemento() {return new IdeaCodeMemento(code,position);}}@Data
public class IdeaCodeMemento {private String code;private Integer position;public IdeaCodeMemento(String code, Integer position) {this.code = code;this.position = position;}
}public class CareTaker {private final Stack<IdeaCodeMemento> mementoStack = new Stack<>();public IdeaCodeMemento getMemento(int num) {IdeaCodeMemento memento = null;while (num-- > 0 && !mementoStack.isEmpty()) {memento = mementoStack.pop();}return mementoStack.isEmpty() ? memento : mementoStack.pop();}public void saveMemento(IdeaCodeMemento memento) {mementoStack.push(memento);}}public class IdeaCodeEditor {public static void main(String[] args) {CareTaker careTaker = new CareTaker();IdeaCodeOriginator originator1 = new IdeaCodeOriginator("hello", 1);careTaker.saveMemento(originator1.createMemento());IdeaCodeOriginator originator2 = new IdeaCodeOriginator("word", 2);careTaker.saveMemento(originator2.createMemento());IdeaCodeOriginator originator3 = new IdeaCodeOriginator("and", 3);careTaker.saveMemento(originator3.createMemento());IdeaCodeOriginator originator4 = new IdeaCodeOriginator("java", 4);careTaker.saveMemento(originator4.createMemento());//撤回到2步前originator4.restoreMemento(careTaker.getMemento(2));System.out.println(originator4); // IdeaCodeOriginator(code=word, position=2)}}

1.1 优化

1)要避免其他类操作或者检查备忘录的内容。

2)备忘录管理者应该具有通用性。

public interface Memento {
}@Data
public class IdeaCodeOriginator {private String code;private Integer position;public IdeaCodeOriginator(String code, Integer position) {this.code = code;this.position = position;}@Dataprivate static class InnerMemento implements Memento {private String code;private Integer position;public InnerMemento(String code, Integer position) {this.code = code;this.position = position;}}public Memento createMemento() {return new InnerMemento(code,position);}public void restoreMemento(Memento memento) throws Exception {if (memento instanceof InnerMemento) {InnerMemento innerMemento = (InnerMemento) memento;this.code = innerMemento.getCode();this.position = innerMemento.position;} else {throw new Exception("类型错误");}}}public class CareTaker<T> {Stack<T> stack = new Stack<>();public T getMemento(int num) {T memento = null;while (num-- > 0 && !stack.isEmpty()) {memento = stack.pop();}return stack.isEmpty() ? memento : stack.pop();}public void saveMemento(T memento) {stack.push(memento);}}public class IdeaCodeEditor2 {public static void main(String[] args) throws Exception {CareTaker<Memento> objectCareTaker = new CareTaker<>();IdeaCodeOriginator originator1 = new IdeaCodeOriginator("hello", 1);objectCareTaker.saveMemento(originator1.createMemento());IdeaCodeOriginator originator2 = new IdeaCodeOriginator("word", 2);objectCareTaker.saveMemento(originator2.createMemento());IdeaCodeOriginator originator3 = new IdeaCodeOriginator("and", 3);objectCareTaker.saveMemento(originator3.createMemento());IdeaCodeOriginator originator4 = new IdeaCodeOriginator("java", 4);objectCareTaker.saveMemento(originator4.createMemento());originator4.restoreMemento(objectCareTaker.getMemento(3)); // IdeaCodeOriginator(code=hello, position=1)System.out.println(originator4);}}

2 优缺点

如果需要为软件提供撤销功能,备忘录模式无疑是一种很好的解决方案。

优点:1)它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤;

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

3 适用场景

1)保存一个对象在某时刻的全部或部分状态,实现撤销操作。

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

相关文章:

备忘录模式-撤销功能的实现

在idea写代码的过程中&#xff0c;会经常用到一个快捷键——“crtl z”,即撤销功能。“备忘录模式”则为撤销功能提供了一个设计方案。 1 备忘录模式 备忘录模式提供一种状态恢复机制。在不破坏封装的前提下&#xff0c;捕获对象内部状态并在该对象之外保存这个状态。可以在…...

C++入门(二)

文章目录 一、缺省参数1、概念2、缺省参数分类1、全缺省参数2、半缺省参数 3、特性总结 二、函数重载1、引入函数重载2、函数重载概念3、函数重载分类4、C支持函数重载的原理--名字修饰(name Mangling) 三、 引用1、引用概念2、引用特性3、 常引用4、 使用场景1、做参数2、做返…...

【软件设计师】面向对象类图的六种关系

面向对象类图的六种关系&#xff08;继承、实现、依赖、关联、聚合、组合&#xff09; 1、泛化&#xff08;继承&#xff09;2、实现3、依赖4、关联5、聚合6、组合 面向对象类图的六种关系&#xff08;继承、实现、依赖、关联、聚合、组合&#xff09; 进行面向对象设计时&…...

二十七、【四种蒙版】

文章目录 图层蒙版剪贴蒙版快速蒙版矢量蒙版 图层蒙版 在当前图层加上蒙版&#xff0c;黑色画笔的可以让当前图层消失&#xff0c;白色的画笔可以让当前图层出现&#xff1a; 无论填充什么样的颜色&#xff0c;蒙板只有黑白灰三种颜色。模板最简单应用就是我们在插入图形的时候…...

卡尔曼家族从零解剖-(00)目录最新无死角讲解

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解的 卡尔曼家族从零解剖 链接 :卡尔曼家族从零解剖-(00)目录最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/133846882 文末正下方中心提供了本人 联系…...

Linux系统之ip命令的基本使用

Linux系统之ip命令的基本使用 一、ip命令介绍1.1 ip命令简介1.2 ip命令的由来1.3 ip命令的安装包 二、ip命令使用帮助2.1 ip命令的help帮助信息2.2 ip命令使用帮助 三、查看网络信息3.1 显示当前网络接口信息3.2 显示网络设备运行状态3.3 显示详细设备信息3.4 查看路由表3.5 查…...

【推荐算法】ctr cvr联合建模问题合集

ctr和cvr分开建模相比ctcvr的优势&#xff1f; 在电商搜索推荐排序中&#xff0c;将ctr和cvr分开建模&#xff0c;相比直接建模ctcvr的优势是什么&#xff1f; - 萧瑟的回答 - 知乎 总结&#xff1a; 1、ctr的数据可以试试获取&#xff0c;能实时训练。但是cvr存在延迟现象&…...

安装njnx --chatGPT

gpt: 要在 Debian 11 上安装 Nginx&#xff08;通常称为 "nginx"&#xff09;&#xff0c;您可以使用 apt 包管理器执行以下步骤&#xff1a; 1. **登录到您的 Debian 11 服务器**。您可以使用 SSH 客户端以 root 或具有管理员权限的用户身份登录。 2. **更新软件…...

性能测试需求分析

1、客户方提出 客户方能提出明确的性能需求&#xff0c;说明对方很重视性能测试&#xff0c;这样的企业一般是金融、电信、银行、医疗器械等&#xff1b;他们一般对系统的性能要求非常高&#xff0c;对性能也非常了解。提出需求也比较明确。 曾经有一个银行项目&#xff0c;已经…...

logback服务器日志删除原理分析

查看以下的logback官方文档 Chapter 4: Appendershttps://logback.qos.ch/manual/appenders.html 按文档说明&#xff0c;maxHistory是设置保存归档日志的最大数量&#xff0c;该数量的单位受到fileNamePattern里的值%d控制&#xff0c;如果有多个%d,只能有一个主%d&#xff0…...

到底什么才是真正的商业智能(BI)

随着人工智能、云计算、大数据、互联网、物联网等新一代信息化、数字化技术在各行各业内开始大规模的应用&#xff0c;社会上的数字化、信息化程度不断加深&#xff0c;而数据价值也在这样的刺激下成为了个人、机构、企业乃至国家的重要战略资源&#xff0c;成为了继土地、劳动…...

Pulsar Manager配置自定义认证插件访问

Pulsar Manager配置自定义认证插件访问 Pulsar Manager和dashboard部署和启用认证 pulsar自定义认证插件开发 前面博客讲了以token方式访问pulsar 这节博客讲如何配置自定义认证插件的方式访问pulsar #启动pulsar-manager docker run --name pulsar-manager -dit \-p 9527:…...

Java SimpleDateFormat linux时间字符串转时间轴的坑

Mon Oct 16 09:51:28 2023 这是linux 的 date命令得到的时间&#xff0c;要转换称时间戳。 EEE MMM dd HH:mm:ss yyyy 这样的格式&#xff0c;看起来就是正确的&#xff0c;可是就是报错 Unparseable date: "Mon Oct 16 09:51:28 2023" 下面是正确的代码 String[…...

202、RabbitMQ 之 使用 fanout 类型的Exchange 实现 Pub-Sub 消息模型---fanout类型就是广播类型

目录 ★ 使用 fanout 类型的Exchange 实现 Pub-Sub 消息模型代码演示&#xff1a;生产者&#xff1a;producer消费者&#xff1a;Consumer01消费者&#xff1a;Consumer02测试结果 完整代码ConnectionUtilPublisherConsumer01Consumer02pom.xml ★ 使用 fanout 类型的Exchange …...

web 性能优化详解(Lighthouse工具、优化方式、强缓存和协商缓存、代码优化、算法优化)

1.性能优化包含的方面 优化性能概念宽泛&#xff0c;可以从信号、系统、计算机原理、操作系统、网络通信、DNS解析、负载均衡、页面渲染。只要结合一个实际例子讲述清楚即可。 2.什么是性能&#xff1f; Web 性能是客观的衡量标准&#xff0c;是用户对加载时间和运行时的直观…...

docker-compose部署elk(8.9.0)并开启ssl认证

docker部署elk并开启ssl认证 docker-compose部署elk部署所需yml文件 —— docker-compose-elk.yml部署配置elasticsearch和kibana并开启ssl配置基础数据认证配置elasticsearch和kibana开启https访问 配置logstash创建springboot项目进行测试kibana创建视图&#xff0c;查询日志…...

解决java.lang.IllegalArgumentException: servlet映射中的<url pattern>[demo1]无效

当我使用tomcat启动使用servlet项目时&#xff0c;出现了报错&#xff1a; java.lang.IllegalArgumentException: servlet映射中的<url pattern>[demo1]无效 显示路径错误&#xff0c;于是去检查Web.xml中的配置&#xff0c;发现是配置文件的路径写错了&#xff0c;少写了…...

软件测试学习(三)易用性测试、测试文档、软件安全性测试、网站测试

目录 易用性测试 用户界面测试 优秀Ul由什么构成 符合标准和规范 直观 一致 灵活 舒适 正确 实用 为有残疾障碍的人员测试&#xff1a;辅助选项测试 测试文档 软件文档的类型 文档测试的重要性 软件安全性测试 了解黑客的动机 威胁模式分析 网站测试 网页基…...

Java中,对象一定在堆中分配吗?

在我们的日常编程实践中&#xff0c;我们经常会遇到各种类型的对象&#xff0c;比如字符串、列表、自定义类等等。这些对象在内存中是如何存储的呢&#xff1f; 你可能会毫不犹豫地回答&#xff1a;“在堆中&#xff01;”如果你这样回答了&#xff0c;那你大部分情况下是正确…...

AI:38-基于深度学习的抽烟行为检测

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌本专栏包含以下学习方向: 机器学习、深度学…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...