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

C++设计模式——Memento备忘录模式

一,备忘录模式的定义

备忘录模式是一种行为型设计模式,它允许将对象的状态保存在外部,并在需要时恢复。

备忘录模式允许在不破坏封装性的前提下,捕获并存储一个对象的内部状态,并在需要时将其恢复到之前的状态。

在某些开发场景,备忘录模式可以用于缓存函数的结果,避免重复计算,以提高性能。

在软件开发中,备忘录模式常应用于某些计算密集型、IO密集型的操作场景,例如数据分析、图形处理等。

备忘录模式在现实生活中的抽象实例:

文本编辑器:当我们在文本编辑器中进行编辑操作时,可以使用撤销功能恢复到之前的状态。

游戏存档:我们可以在游戏中存档,以便下次打开时恢复到之前的游戏进度。

浏览器的缓存:浏览器中的历史记录可以帮助我们返回到之前访问的页面。

操作系统:在操作系统中,我们可以使用撤销功能来避免误操作。

二,备忘录模式的结构

备忘录模式主要包含以下组件:

1.发起人(Originator):

它会在需要保存自身状态时创建一个备忘录对象,并在后续场景使用备忘录对象来恢复自身状态。

2.备忘录(Memento):

用来获取和设置对象的内部状态。

3.管理者(Caretaker):

用来管理多个备忘录对象。

组件之间的工作步骤如下:

1.客户端创建和使用发起人对象。发起人对象可以有一个内部状态,客户端可以改变该状态。

2.客户端通过调用发起人对象的方法来创建备忘录对象,并将发起人对象的当前状态保存到备忘录中。

3.客户端将备忘录对象交给管理者对象进行保存。

4.在需要时,客户端可以从管理者对象获取备忘录对象,并将发起人对象的状态恢复到备忘录对象所保存的状态。

备忘录模式的核心在于,发起人对象和管理者对象之间是分离的,保证了发起人对象的状态可以在不影响封装性和隐藏性的情况下被保存和恢复。

对应UML类图:

三,备忘录模式代码样例

Demo1:

#include <iostream>
#include <string>
#include <vector>class Originator {
private:std::string state;
public:void SetState(const std::string& newState) {state = newState;}std::string GetState() const {return state;}class Memento {private:std::string state;public:Memento(const std::string& originatorState){state = originatorState;}std::string GetSavedState() const {return state;}};Memento CreateMemento() const {return Memento(state);}void RestoreState(const Memento& memento) {state = memento.GetSavedState();}
};class Caretaker {
private:std::vector<Originator::Memento> mementos;
public:void AddMemento(const Originator::Memento& memento) {mementos.push_back(memento);}Originator::Memento GetMemento(int index) const {if (index >= 0 && index < mementos.size()) {return mementos[index];}throw std::out_of_range("Invalid Memento index");}
};int main() {Originator originator;Caretaker caretaker;originator.SetState("State 1");caretaker.AddMemento(originator.CreateMemento());originator.SetState("State 2");caretaker.AddMemento(originator.CreateMemento());originator.SetState("State 3");caretaker.AddMemento(originator.CreateMemento());std::cout << "Current state: "<< originator.GetState() << std::endl;originator.RestoreState(caretaker.GetMemento(2));std::cout << "Current state: "<< originator.GetState() << std::endl;return 0;
}

运行结果:

Current state: State 3
Current state: State 3

Demo2:

#include <iostream>
#include <string>
#include <vector>class Memento {
private:int state;
public:Memento(int s) : state(s) {}int getState() const { return state; }
};class Originator {
private:int currentState;
public:void setState(int newState) {currentState = newState;}Memento createMemento() {return Memento(currentState);}void restoreFromMemento(Memento& memento) {currentState = memento.getState();}void getState() {std::cout << "Current state: " << currentState << std::endl;}
};class CareTaker {
private:std::vector<Memento> memoranda;
public:void saveMemento(Originator& originator) {memoranda.push_back(originator.createMemento());}void restoreOriginatorToState(Originator& originator, size_t index) {originator.restoreFromMemento(memoranda[index]);}Memento getMemento(int index) const {if (index >= 0 && index < memoranda.size()) {return memoranda[index];}throw std::out_of_range("Invalid Memento index");}
};int main() {Originator originator;CareTaker caretaker;originator.setState(5);caretaker.saveMemento(originator);originator.getState();originator.setState(10);caretaker.saveMemento(originator);originator.getState();originator.setState(15);caretaker.saveMemento(originator);originator.getState();originator.setState(20);originator.getState();caretaker.restoreOriginatorToState(originator, 1);originator.getState();return 0;
}

运行结果:

Current state: 5
Current state: 10
Current state: 15
Current state: 20
Current state: 10

四,备忘录模式的应用场景

网络请求:当网络服务频繁收到请求时,备忘录模式可以缓存响应结果,降低网络延迟。

算法优化:搜索或排序算法可能存在递归操作,备忘录模式可以帮助记录中间结果,避免重复搜索。

图形渲染:在游戏或图形等开发场景,备忘录模式可以避免复杂的图形结构被反复渲染。

五,备忘录模式的优缺点

备忘录模式的优点:

提供了对象状态的保存和恢复功能,使得系统更加灵活。

提供了一种简单的撤销/重做机制。

通过将结果进行缓存,避免了重复处理,提升了系统性能。

备忘录模式的缺点:

如果需要保存的状态数量很多,可能会占用较多的内存。

如果没有对外部访问备忘录对象的权限进行限制,可能会破坏封装性。

如果应用不当会使得代码结构更加复杂。

六,代码实战

Demo:模拟文本编辑器的撤销功能

#include <iostream>
#include <string>
#include <vector>class TextMemento {
public:TextMemento(const std::string& text){text_ = text;}const std::string& getText() const {return text_;}
private:std::string text_;
};class TextEditor {
public:void setText(const std::string& text) {text_ = text;}const std::string& getText() const {return text_;}TextMemento createMemento() {return TextMemento(text_);}void restoreMemento(const TextMemento& memento) {text_ = memento.getText();}
private:std::string text_;
};int main() {TextEditor editor;std::vector<TextMemento> history;editor.setText("Hello, World!");history.push_back(editor.createMemento());editor.setText("Goodbye!");history.push_back(editor.createMemento());std::cout << "Current Text: " << editor.getText() << std::endl;editor.restoreMemento(history[0]);std::cout << "After Undo: " << editor.getText() << std::endl;editor.restoreMemento(history[1]);std::cout << "After Redo: " << editor.getText() << std::endl;return 0;
}

运行结果:

Current Text: Goodbye!
After Undo: Hello, World!
After Redo: Goodbye!

七,参考阅读

https://softwarepatterns.com/cpp/memento-software-pattern-cpp-example

https://www.scaler.com/topics/memento-design-pattern/

https://sourcemaking.com/design_patterns/memento

https://www.geeksforgeeks.org/memento-design-pattern-c-design-patterns/

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 谷粒商城-P125【gulimall-search】:更改 elasticsearch 版本不生效
  • 【电子通识】半导体工艺——刻蚀工艺
  • C语言指针详解与应用
  • HTML/CSS/JS学习笔记 Day4(HTML--C3 表格)
  • AI预测地球未来,温室效应失控?地球变金星?
  • Dubbo 与 Zookeeper 在项目中的应用:原理与实现详解
  • unocss 一直热更新打印[vite] hot updated: /__uno.css
  • C语言 ——— 学习并使用 #if defined #ifdef #ifndef 条件编译指令
  • C++第五节 - this指针、构造函数、析构函数
  • 讯方·智汇云校北京校区
  • Result 和 自定义异常 在前后端交互中的作用
  • 数据结构之算法的分析和应用
  • 多速率信号处理
  • langgraph tool如何获取上下文和RunableConfig
  • C语言从头学58——学习头文件math.h(一)
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • css选择器
  • Javascript Math对象和Date对象常用方法详解
  • Java多态
  • JDK 6和JDK 7中的substring()方法
  • Laravel 菜鸟晋级之路
  • Python连接Oracle
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 动态魔术使用DBMS_SQL
  • 普通函数和构造函数的区别
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 新书推荐|Windows黑客编程技术详解
  • 学习JavaScript数据结构与算法 — 树
  • # 飞书APP集成平台-数字化落地
  • #进阶:轻量级ORM框架Dapper的使用教程与原理详解
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (2)Java 简介
  • (3)(3.5) 遥测无线电区域条例
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • (蓝桥杯每日一题)love
  • (十五)使用Nexus创建Maven私服
  • (一)、python程序--模拟电脑鼠走迷宫
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Core 发展历程和版本迭代
  • .NET Remoting学习笔记(三)信道
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET连接数据库方式
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示
  • @RequestBody与@ModelAttribute
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——
  • [C#]C#学习笔记-CIL和动态程序集
  • [C#]OpenCvSharp结合yolov8-face实现L2CS-Net眼睛注视方向估计或者人脸朝向估计
  • [CF]Codeforces Round #551 (Div. 2)