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

news2024/11/24 18:29:44

一,备忘录模式的定义

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

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

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

在软件开发中,备忘录模式常应用于某些计算密集型、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/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IT前端好用的工具集

在线抠图网站 https://www.remove.bg/ 将iconfont转成css显示 https://transfonter.org/ 免费的在线图片压缩 https://tinypng.com/ JSON在线格式化工具 https://www.sojson.com/ 国内人工智能kimi.moonshot工具 https://kimi.moonshot.cn/chat/crft7a6sdv14grouufs0 自动…

2024年录屏神器大盘点,轻松捕捉屏幕精彩

现在讲解一些操作越来越便捷了&#xff0c;我 一般都是用录屏工具来边录制操作边讲解&#xff0c;这样可以更方便对方了解操作步骤。这次我就分享几款免费录屏工具一起来试试吧。 1.福晰录屏软件 链接&#xff1a;www.foxitsoftware.cn/REC/ 对于初次尝试录屏的新手来说&…

java语言发展史

Java语言的发展史是一部丰富多彩的科技演进史&#xff0c;它从一个简单的项目逐渐成长为全球范围内广泛使用的高级编程语言。下面&#xff0c;我将带您简要回顾Java的发展历程。 起源&#xff1a;Oak阶段&#xff08;1991-1995&#xff09; Java的前身是Oak&#xff0c;由詹姆斯…

【软考】设计模式之责任链模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. 适用性6. 优点7. 缺点8. java示例 1. 说明 1.使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。2.将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为…

【漏洞复现】易天智能eHR CreateUser 任意用户添加漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

81页PPT产业园5G多功能智慧灯杆整体规划设计方案

学习9000多份智慧城市&#xff0c;智慧医院&#xff0c;智能制造&#xff0c;数字化转型&#xff0c;新质生产力&#xff0c;算力&#xff0c;大模型&#xff0c;AIGC&#xff0c;工业互联网&#xff0c;数字孪生......持续更新热点行业解决方案&#xff0c;公号智慧方案文库。…

计算机网络 --- 【2】计算机网络的组成、功能

目录 一、计算机网络的组成 1.1 从组成部分看 1.2 从工作方式看 1.3 从逻辑功能看 1.4 总结 二、计算机网络的功能 2.1 数据通信 2.2 资源共享​编辑 2.3 分布式处理 2.4 提高可靠性 2.5 负载均衡 一、计算机网络的组成 1.1 从组成部分看 我们举例分析计算机网络从…

Mistral.rs开源大语言模型(LLM)推理平台兼容OpenAI API,通过HTTP服务器和Python绑定

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

十、组合模式

组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许将对象组合成树形结构来表示“部分-整体”的层次关系。组合模式能够让客户端以统一的方式对待单个对象和对象集合&#xff0c;使得客户端在处理复杂树形结构的时候&#xff0c;可以以…

读者来信:《人机环境系统智能》读后感

一、什么是智能&#xff1f; 当“人工智能”火爆出圈乃至登堂入室&#xff0c;上升为国家战略层面后&#xff0c;尽管我们每天都把人工智能挂在嘴上&#xff0c;但好像似乎忘了问一句&#xff1a;什么是智能&#xff1f;经过一番在哲学上对控制论、信息论、系统论在哲学上的追根…

MES实施困难点简述

调研数据显示&#xff0c;企业认为多部门协调难度大、各类数据采集难度大、定制化程度高是MES系统实施过程中最为突出的三个难点&#xff0c;比例分别达到52%、48%、46%。其他如对MES认识不足、难以准确把握需求、企业相关人才比较匮乏、与其他系统边界难以划分等也是实施过程中…

加密与安全_优雅存储用户密码的最佳实践

文章目录 Pre概述最佳实践避免使用MD5、SHA1等快速哈希算法加盐哈希 &#xff08;不推荐&#xff09;使用BCrypt、Argon2等慢哈希算法 (推荐)BCrypt Code1. 自动生成和嵌入盐2. 哈希结果的格式3. 代价因子 BCrypt特点 防止暴力破解1. 登录失败锁定2. 双因素认证&#xff08;2FA…

MATLAB | 绘图复刻(十七) | 半小提琴图

嘿&#xff0c;真的是好久不见&#xff0c;最近有点过于忙了&#xff0c;今天更一个好久之前粉丝问的半小提琴图的绘制方法&#xff0c;要复刻这张图&#xff1a; 绘制效果如下&#xff1a; 还是挺好看的&#xff0c;下面直接进入正题&#xff1a; 教程部分 0 数据准备 这里…

Redis学习Day3——项目工程开发

扩展阅读推荐&#xff1a; 黑马程序员Redis入门到实战教程_哔哩哔哩_bilibili 一、项目介绍及其初始化 学习Redis的过程&#xff0c;我们还将遇到各种实际问题&#xff0c;例如缓存击穿、雪崩、热Key等问题&#xff0c;只有在实际的项目实践中解决这些问题&#xff0c;才能更好…

DPDI基础版安装部署说明

DispatchPDI下载 DPDI online部署包下载地址&#xff1a; Windows: http://files.pizzalord.site/api/public/dl/7Tnq6ScE/release/dpdi-community-win.zip Linux: http://files.pizzalord.site/api/public/dl/otCt9WuI/release/dpdi-community-linux.zip DPDI部署 DPDI应…

python构建深度学习模型开发数据采集利器,为模型提供充足图像数据

经常需要接触到各种各样的图像数据&#xff0c;为模型开发准备素材&#xff0c;在实际的项目中&#xff0c;一部分数据来源于真实的项目场景&#xff0c;但是这部分数据大都比较少&#xff0c;且获取的难度比较大&#xff0c;往往都是项目到了实施阶段的时候才有机会拿到数据&a…

基于SpringBoot的医院挂号预约管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的医院挂号预约管理…

【有啥问啥】探索扫地机器人中的 SLAM 算法:原理、实现与未来展望

探索扫地机器人中的 SLAM 算法&#xff1a;原理、实现与未来展望 随着智能家居的普及&#xff0c;扫地机器人逐渐成为日常生活中的常见家电。其自主导航能力使得它能够在复杂的家庭环境中高效完成清洁任务&#xff0c;而这背后的核心技术之一就是 SLAM&#xff08;Simultaneou…

CCS12.2 以及以上版本如何使用C2000ware 4.03版本,发现直接导入工程不能正确识别地址变量?

C2000ware 5.02 地址变量为&#xff1a;COM_TI_C2000WARE_INSTALL_DIR&#xff0c;CCS12.2以上版本能够直接匹配识别&#xff01; 但是C2000ware4.03版本地址变量为&#xff1a;COM_TI_C2000WARE_SOFTWARE_PACKAGE_INSTALL_DIR&#xff0c;这个不能直接识别到头文件的地址&…

appium server gui详细按照步骤

1.安装appium server desktop Appium安装提供两种方式:桌面版和命令行版。其中桌面版又分为 Appium GuI 和 Appium Desktop 。作为初学者&#xff0c;用桌面版&#xff0c;对初学者比较友好。 官网下载地址&#xff1a;Releases appium/appium-desktop GitHubTags appium/…