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

Qt C++设计模式->备忘录模式

备忘录模式(Memento Pattern)是一种行为型设计模式,用于在不破坏封装性的前提下,捕获并保存对象的内部状态,以便在将来的某个时刻可以恢复到之前的状态。备忘录模式的核心是状态的保存和恢复,常用于实现撤销、回滚等功能。

备忘录模式的应用场景

备忘录模式特别适合以下场景:

  1. 撤销/恢复操作:例如文本编辑器中的撤销功能,通过备忘录保存每次操作的状态,用户可以随时回到某个历史状态。

  2. 数据快照:保存对象在某个时刻的快照,以便之后回溯或调试。

  3. 事务管理:在处理复杂的事务时,可以在中间点保存状态,当某个操作失败时,回滚到之前的状态。

备忘录模式的核心

备忘录模式的主要组成部分包括:

  1. 发起者(Originator):负责创建并恢复备忘录,保存当前的状态到备忘录中,或者从备忘录中恢复状态。

  2. 备忘录(Memento):用于存储发起者的内部状态,不对外公开备忘录的实现细节。

  3. 负责人(Caretaker):负责保存和管理备忘录,但不会操作或修改备忘录的内容。它只知道备忘录保存的状态,并在需要时将备忘录传递回发起者进行状态恢复。

备忘录模式强调的是封装性,发起者的内部状态不应该对外暴露,备忘录类也应该避免暴露这些细节。

备忘录模式的示例代码

假设我们在开发一个文本编辑器,并希望提供撤销和恢复功能,每当用户输入一段文本时,我们将保存当前状态,以便用户可以随时撤销操作。

1. 定义发起者、备忘录和负责人

#include <QDebug>
#include <QString>
#include <QStack>// 备忘录类:保存文本编辑器的状态
class Memento {
private:QString state;  // 保存的状态public:Memento(const QString& state) : state(state) {}QString getState() const {return state;  // 返回保存的状态}
};// 发起者类:文本编辑器
class TextEditor {
private:QString text;  // 当前的文本状态public:void setText(const QString& newText) {text = newText;}QString getText() const {return text;}// 创建备忘录,保存当前状态Memento* save() const {return new Memento(text);}// 从备忘录中恢复状态void restore(Memento* memento) {if (memento) {text = memento->getState();}}
};// 负责人类:管理备忘录
class Caretaker {
private:QStack<Memento*> history;  // 保存备忘录的栈public:void saveMemento(Memento* memento) {history.push(memento);  // 保存当前状态的备忘录}Memento* undo() {if (!history.isEmpty()) {Memento* lastState = history.pop();  // 取出最后一个保存的备忘录return lastState;}return nullptr;  // 没有更多历史状态}~Caretaker() {// 清理保存的备忘录while (!history.isEmpty()) {delete history.pop();}}
};// 使用示例
int main() {TextEditor* editor = new TextEditor();Caretaker* caretaker = new Caretaker();// 初始文本editor->setText("Hello");qDebug() << "Current text:" << editor->getText();  // 输出:Current text: Hello// 保存状态caretaker->saveMemento(editor->save());// 用户修改文本editor->setText("Hello, World");qDebug() << "Current text after modification:" << editor->getText();  // 输出:Current text after modification: Hello, World// 再次保存状态caretaker->saveMemento(editor->save());// 用户再次修改文本editor->setText("Hello, Qt!");qDebug() << "Current text after second modification:" << editor->getText();  // 输出:Current text after second modification: Hello, Qt!// 执行撤销操作editor->restore(caretaker->undo());qDebug() << "Current text after undo:" << editor->getText();  // 输出:Current text after undo: Hello, World// 再次执行撤销操作editor->restore(caretaker->undo());qDebug() << "Current text after second undo:" << editor->getText();  // 输出:Current text after second undo: Hello// 清理内存delete editor;delete caretaker;return 0;
}

代码解析

  • Memento类:这是备忘录类,负责保存发起者的状态。在这个例子中,它保存文本编辑器中的文本状态,并通过getState方法提供对状态的访问。

  • TextEditor类:这是发起者类,它拥有当前的文本状态,并且可以创建备忘录来保存当前状态或从备忘录中恢复状态。

  • Caretaker类:这是负责人类,它保存所有的备忘录(通过栈存储历史状态),并在需要时将备忘录返回给发起者进行状态恢复。undo方法从栈中弹出最后保存的状态,模拟撤销操作。

  • 客户端代码:客户端通过修改文本,并在每次修改后保存状态。通过调用Caretakerundo方法,客户端可以恢复到之前的文本状态,模拟撤销操作。

备忘录模式的优点

  • 保存历史状态:备忘录模式允许你保存对象的状态,并在将来恢复这些状态。非常适合实现撤销、恢复、回滚等功能。

  • 封装性好:备忘录类不暴露发起者的内部状态,保证了发起者的封装性。发起者和负责人只通过备忘录进行状态的保存和恢复,而不需要直接操作发起者的状态。

  • 减少耦合:负责人只负责保存和管理备忘录,而不直接参与发起者的逻辑,职责清晰。

备忘录模式的缺点

  • 内存开销大:每次保存对象的状态都需要创建一个新的备忘录对象,尤其是当对象状态非常庞大时,可能会导致大量的内存占用。

  • 实现复杂性:如果对象的状态非常复杂,备忘录模式的实现也会相应复杂,尤其是在需要保存多个部分或大对象时。

适合使用备忘录模式的情况

  • 需要实现撤销/恢复操作:例如文本编辑器、绘图工具、IDE等支持撤销/恢复功能的应用程序。

  • 需要保存对象的历史状态:当系统需要定期保存某些对象的状态以便将来回溯时,可以使用备忘录模式。

  • 需要避免直接暴露内部状态:如果需要在多个地方保存对象的状态,但不想让外界直接访问或修改对象的内部状态,备忘录模式是一个很好的选择。

不适合使用备忘录模式的情况

  • 对象状态非常庞大:如果发起者的状态非常庞大,频繁创建备忘录会带来较大的内存开销,不适合使用备忘录模式。

  • 状态变化频繁:如果对象状态变化频繁,并且每次都需要保存,那么备忘录模式会带来大量性能问题。

Qt中的备忘录模式应用

在Qt开发中,备忘录模式可以用于实现撤销/恢复功能。例如,在一个文本编辑器或绘图工具中,用户的每次操作都可能改变对象的状态,这些操作可以通过备忘录模式保存下来,并在需要时回滚或恢复。Qt中有些类(如QUndoStack)可以直接实现类似的撤销功能,它们内部也可能应用了备忘录模式的思想。

总结

备忘录模式通过保存对象的状态并在将来进行恢复,使得系统能够实现撤销、回滚等功能,同时保证了对象内部状态的封装性。它非常适合用于保存对象的历史状态、支持撤销操作的场景。然而,备忘录模式的内存开销较大,不适合频繁状态变化且状态庞大的对象。

相关文章:

Qt C++设计模式->备忘录模式

备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为型设计模式&#xff0c;用于在不破坏封装性的前提下&#xff0c;捕获并保存对象的内部状态&#xff0c;以便在将来的某个时刻可以恢复到之前的状态。备忘录模式的核心是状态的保存和恢复&#xff0c;常用于实现撤销…...

Vue使用@别名替换后端ip地址

1. 安装 types/node types/node 包允许您在TypeScript项目中使用Node.js的核心模块和API&#xff0c;并提供了对它们的类型检查和智能提示的支持。 npm install types/node --save-dev 比如安装之后&#xff0c;就可以导入nodejs的 path模块&#xff0c;在下面代码 import path…...

强大的PDF到Word转换工具

Solid Converter&#xff1a;强大的PDF到Word转换工具推荐 在日常工作和学习中&#xff0c;PDF是最常用的文件格式之一。然而&#xff0c;编辑PDF文档并不总是那么方便&#xff0c;尤其是当你需要将PDF文件转换为Word文档时。Solid Converter 是一款强大的工具&#xff0c;专为…...

js进阶——深入解析JavaScript中的URLSearchParams

深入解析 JavaScript 中的 URLSearchParams 在现代Web开发中&#xff0c;我们经常需要处理URL中的查询参数&#xff0c;尤其是在构建动态Web应用时。这些查询参数&#xff08;query parameters&#xff09;通常以 ?keyvalue&key2value2 的形式存在。JavaScript 提供了一个…...

如何利用wsl-Ubuntu里conda用来给Windows的PyCharm开发

前提&#xff1a;咱们在wsl-Ubuntu上&#xff0c;有conda的虚拟环境 咱们直接打开PyCharm,打开Settings 更换Python Interpreter即可 当然一开始可能没有下面的选项&#xff0c;需要我们点击右边的Add Interpreter 这里选择wsl 点击next 将这两步进行修改 可以看出来&#xff0…...

操作系统的了解及安装

一、linux系统认识 linux是指操作系统的内核&#xff0c;ubuntu是指基于这种内核的操作系统&#xff0c;Ubuntu属于Linux的一个发行版本&#xff0c;有简易的用户界面&#xff0c;完善的包管理系统&#xff0c;Ubuntu还对大多数硬件有着良好的兼容性&#xff0c;包含最新的图形…...

【C++篇】虚境探微:多态的流动诗篇,解锁动态的艺术密码

文章目录 C 多态详解&#xff08;进阶篇&#xff09;前言第一章&#xff1a;多态的原理1.1 虚函数表的概念1.1.1 虚函数表的生成过程 1.2 虚表的存储位置 第二章&#xff1a;动态绑定与静态绑定2.1 静态绑定2.1.1 静态绑定的实现机制&#xff1a;2.1.2 示例代码&#xff1a; 2.…...

uniapp的相关知识(1)

1、hover-class&#xff1a;当有鼠标按下时&#xff0c;会切换对应的样式&#xff1b;也可以设置对应的变色时间。 2、selectable&#xff1a;设置text组件的文本是否可以进行复制。 3、with&#xff1a;当设置为80%时&#xff0c;表示宽占整个屏幕的80%。 4、border&#x…...

uniapp生成随机数

推荐学习文档 golang应用级os框架&#xff0c;欢迎stargolang应用级os框架使用案例&#xff0c;欢迎star案例&#xff1a;基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识&#xff0c;这里有免费的golang学习笔…...

使用jenkins将airflow-dbt部署到服务器上

系列文章目录 文章目录 系列文章目录课程地址YT一、jenkins服务器的初始化配置1.1 运行第一个jenkins pipeline二、编写本地dbt项目2.1 克隆git上的初始文件到本地2.2 本地创建虚拟环境2.3 创建airflow的Dockerfile2.4 安装dbt2.5 创建dbt所需要的snowflake数据库2.6 配置docke…...

初学java练习题【1】

import java.util.Scanner;public class HelloWorld{public static void main(String[] args){Scanner scannernew Scanner(System.in);//输入工资System.out.println("请输入您的工资&#xff1a;");double d1scanner.nextDouble();System.out.println("请输入…...

大模型应用探讨,免费AI写作、一键PPT、免费PDF百种应用、与AI对话

大模型应用平台知识普及, 应用可见评论区 我们生活在一个充满无限可能的数字时代&#xff0c;人工智能技术正在推动着各种创新的边界。大模型应用平台一般包含以下功能。 ## 1. 一键生成论文 写作是学生、研究人员和职场人士都无法避免的任务。大模型应用平台拥有强大的文本生…...

计算机视觉之OpenCV vs YOLO

好多开发者希望搞明白OpenCV 和YOLO区别&#xff0c;实际上&#xff0c;二者在计算机视觉领域都有广泛应用&#xff0c;但它们有很大的不同。 一、OpenCV 概述 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它…...

【深度学习基础模型】胶囊网络(Capsule Networks, CapsNet)详细理解并附实现代码。

【深度学习基础模型】胶囊网络&#xff08;Capsule Networks, CapsNet&#xff09;详细理解并附实现代码。 【深度学习基础模型】胶囊网络&#xff08;Capsule Networks, CapsNet&#xff09;详细理解并附实现代码。 文章目录 【深度学习基础模型】胶囊网络&#xff08;Capsul…...

科普向 -- 什么是RPC

科普向 – 什么是RPC RPC&#xff0c;全称为远程过程调用&#xff08;Remote Procedure Call&#xff09;&#xff0c;是一种计算机通信协议&#xff0c;允许程序在不同的地址空间&#xff08;通常是不同的计算机&#xff09;上执行代码。RPC使得程序可以像调用本地函数一样调…...

SpringBoot教程(二十四) | SpringBoot实现分布式定时任务之Quartz(基础)

SpringBoot教程&#xff08;二十四&#xff09; | SpringBoot实现分布式定时任务之Quartz&#xff08;基础&#xff09; 简介适用场景Quartz核心概念Quartz 存储方式Quartz 版本类型引入相关依赖开始集成方式一&#xff1a;内存方式(MEMORY)存储实现定时任务1. 定义任务类2. 定…...

【现代控制理论】第2-5章课后题刷题笔记

文章目录 第二章&#xff1a;线性控制系统的状态空间描述第三章&#xff1a;控制系统状态空间描述的特性3.1 计算状态转移矩阵&#xff08;矩阵指数函数&#xff09;3.2 计算系统的时间响应&#xff08;状态方程的解&#xff09;3.3 判断系统的能控性和能观性&#xff0c;以及能…...

(四)Proteus仿真STM32单片机使用定时器控制LED

&#xff08;四&#xff09;Protues仿真STM32单片机使用定时器控制LED – ARMFUN 定时器在单片机中具有重要的作用&#xff0c;它可以提供精确的时间控制和事件触发功能。相比之下&#xff0c;使用延时函数&#xff08;delay function&#xff09;来实现时间控制存在以下一些坏…...

Python快速编程小案例——打印蚂蚁森林植树证书

提示&#xff1a;&#xff08;个人学习&#xff09;&#xff0c;案例来自工业和信息化“十三五”人才培养规划教材&#xff0c;《Python快速编程入门》第2版&#xff0c;黑马程序员◎编著 蚂蚁森林是支付宝客户端发起“碳账户”的一款公益活动:用户通过步行地铁出行、在线消费等…...

Cherno游戏引擎笔记(61~72)

---------------一些维护和更改------------- 》》》》 Made Win-GenProjects.bat work from every directory 代码更改&#xff1a; echo off->pushd ..\->pushd %~dp0\..\call vendor\bin\premake\premake5.exe vs2019popdPAUSE 为什么要做这样的更改&#xff1f; …...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

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

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

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...