备忘录模式-C++实现

备忘录是一种行为型设计模式,它允许在不破坏封装性的前提下捕获和恢复一个对象的内部状态。它将对象的内部状态保存到备忘录对象中,并在需要的时候从备忘录中取出恢复状态,实现了状态的保存和恢复。

备忘录有以下三个角色:

1、发起人(Originator):是需要备份和恢复状态的对象。它能够创建备忘录对象,并可以从备忘录中恢复状态。

2、备忘录(Memento):用于存储发起人对象的状态,备忘录可以保持任意类型的状态数据,但不对外公开。

3、管理者(Caretaker):负责管理者对象,包括保存和提供备忘录,它通常只保存最后一次备忘录对象。

工作流程:

1、发起人创建备忘录对象,并将自身状态存储到备忘录中。

2、发起人可以在任何时候从备忘录中恢复状态,将备忘录中保存的状态数据还原到自身。

举例:

假设我们现在有一组int类型的数据,用户在界面上修改了这组数据的值,但最后用户不想保存。

#include <iostream>
#include <memory>
#include <vector>// 备忘录对象
class Memento
{
public:Memento(const std::vector<int>& _data): data_(_data){}std::vector<int> GetMemento(){return data_;}private:std::vector<int> data_;
};// 发起人
class Originator
{
public:void SetData(const std::vector<int>& _data){data_ = _data;}// 创建备忘录std::shared_ptr<Memento> CreateMemento(){return std::make_shared<Memento>(data_);}// 恢复状态void RestoreMemento(std::shared_ptr<Memento> _memento){data_ = _memento->GetMemento();}// 输出数据void PrintData(){for (int i = 0; i < data_.size(); i++)std::cout << data_[i] << " ";std::cout << std::endl;}private:std::vector<int> data_;
};// 管理者对象
class Caretaker
{
public:void AddMemento(std::shared_ptr<Memento> _memento){history_.emplace_back(_memento);}std::shared_ptr<Memento> GetMemento(const int& idx){if (history_.size() <= idx)return nullptr;std::shared_ptr<Memento> temp = history_[idx];history_.erase(history_.begin() + idx);return temp;}private:std::vector<std::shared_ptr<Memento>> history_;
};

代码示例中,我们首先创建了一个备忘录类,实现的方法有获取该备忘录对象的状态,这个状态是在构造的时候传进去并保存下来。然后创建了一个发起人类,实现了设置状态、创建备忘录对象、恢复状态、输出状态的方法。最后创建了一个备忘录管理者对象,用于管理所有发起人创建的备忘录对象,实现的方法有添加备忘录对象、从备忘录管理列表里取出一个对象。

测试:

void TestMemento()
{// 创建初始数据std::vector<int> data = { 1, 2, 3, 4, 5 };// 创建发起人std::shared_ptr<Originator> originator = std::make_shared<Originator>();// 创建备忘录管理者std::shared_ptr<Caretaker> careTaker = std::make_shared<Caretaker>();originator->SetData(data);std::shared_ptr<Memento> memento = originator->CreateMemento();// 存到备忘录管理者careTaker->AddMemento(memento);originator->PrintData();std::cout << "-----------------------" << std::endl;// 用户修改后的数据为std::vector<int> data1 = { 1,3,4,2,1 };originator->SetData(data1);// 创建备忘录并保存状态std::shared_ptr<Memento> memento1 = originator->CreateMemento();careTaker->AddMemento(memento1);originator->PrintData();std::cout << "-----------------------" << std::endl;// 用户不想保存修改后的数据,我们来恢复originator->RestoreMemento(careTaker->GetMemento(0));originator->PrintData();}

测试代码示例中,我们先创建了一组数据(1,2,3,4,5)作为我们的初始数据,并把这个数据保存到备忘录中。然后模拟用户修改数据为(1,3,4,2,1),也把这个数据保存到备忘录中。最后用户不想保存修改后的数据,那我们就需要把数据恢复到初始状态。

输出:

1 2 3 4 5
-----------------------
1 3 4 2 1
-----------------------
1 2 3 4 5

备忘录模式遵循以下原则:

1、单一职责原则:备忘录对象负责存储对象的状态、发起人负责创建备忘录和恢复对象状态、管理者类负责管理备忘录对象。每个类有明确的责任。

2、开放封闭原则:备忘录模式允许发起人随意的增加备忘录和恢复状态,无需修改现有的代码,符合开放封闭原则。

优点:

1、状态保存和恢复:备忘录模式可以通过在发起人类和备忘录类之间引入备忘录对象,实现对象状态的保存和恢复。这样可以将对象的状态从发起人类中分离出来,以实现更好的封装性和隔离性。

2、简化发起人类:因为备忘录模式可以减轻发起人类的负担,因为它把发起人类的状态保存和恢复委托给了备忘录类和备忘录管理者类,这样使得发起人类更加简单并且易于维护。

3、支持多次恢复:备忘录模式允许备忘录管理者类中添加多个状态,这样可以支持多次恢复操作,这使得系统具有撤销和重做的能力。

缺点:

1、多个备忘录对象的管理:如果需要管理大量的备忘录对象,可能会增加备忘录管理者的复杂性。

2、内存消耗问题:如果要保存的对象状态数量很大或者状态很大时,需要占用更多的内存。

3、状态一致性问题:因为备忘录模式将发起人的状态分散开来,如果发起人的其他操作依赖于状态时,需要保持一致性。

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

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

相关文章

Mybatis-Plus条件构造器Wrapper

常用的两种条件构造器分别是 QueryWrapper 和 LambdaQueryWrapper QueryWrapper Autowiredprivate StudentMapper studentMapper;Testpublic void test() {//条件分页查询学生&#xff0c;性别为2&#xff08;代表女&#xff09;&#xff0c;年龄大于等于12的学生QueryWrapper&…

树和二叉树的基本概念和堆的实现

树的概念及结构 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 1.有一个特殊的结点&#…

04-配置远程仓库的SSH免密登陆

配置SSH免密登录 配置步骤 创建好的远程仓库也可以使用SSH的方式进行访问,但如果没有配置公钥会有警告 第一步: 删除用户家目录下的.ssh目录,如果没有该目录或者该目录下已经有密钥了就不用执行该操作 #进入当前用户的家目录,删除.ssh 目录 LayneLAPTOP-Layne MINGW64 ~ $ r…

python datetime 获取特定一天的后一天或者后几天

这里写自定义目录标题 1 获取特定天的时间对象 具体时间格式参考&#xff1a;Python time strptime()和strftime()-CSDN博客 import datetimetimer datetime.datetime.strptime(date, "%Y-%m-%d")2 获取下一天或者【下x天】的数据并进行格式转换 # 下一天数据 ne…

基于SpringBoot+Vue的前后端分离的房屋租赁系统2

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 开发过程中&#xff0…

uniApp打包的手机app如果用户没开启通知权限、引导用户开启

封装一个setPermissions.js文件 /*** 如果用户没开启通知权限、引导用户开启 */ export function setPermissions() {// #ifdef APP-PLUS if (plus.os.name Android) {var main plus.android.runtimeMainActivity();var pkName main.getPackageName();var uid main.getApp…

基于WebSocket实现客户聊天室

目录 一、实现聊天室原理 二、聊天室前端代码 三、聊天室后端代码&#xff08;重点&#xff09; 四、聊天室实现效果展示 一、实现聊天室原理 1.1 介绍websocket协议 websocket是一种通信协议&#xff0c;再通过websocket实现弹幕聊天室时候&#xff0c;实现原理是客户端首…

Dynamo初学配置

配置参考 视频参考 Dynamo之Python编程视频教学_dynamo python-CSDN博客 升级Python3参考【需要Revit2020版本&#xff0c;2019版本不适用】 Dynamo 升级使用 Python3教程_dynamo升级找不到cpython-CSDN博客 Dynamo数据淘金——01//升级配置Dynamo - 哔哩哔哩 dynamo中pyt…

【动态规划】LeetCode-931.下降路径最小和

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…

jira配置https访问-running-jira-applications-over-ssl-or-https

命令行配置步骤 Command line installation 过程说明&#xff1a; 创建存放证书的本地秘钥库keystore文件jira.jks&#xff0c;生成证书签名请求文件csr.txt或者jira.csr&#xff1b; 自签名&#xff0c;生成密钥和根证书&#xff1b; 使用根证书ca.crt对csr.txt进行签名&…

求二叉树叶子结点个数或求二叉树非叶子结点个数。

题目描述&#xff1a;求二叉树叶子结点个数。 分析&#xff1a; 考虑递归和非递归两种方法 <1>递归 int Leaves(BiTree T){if(T NULL)return 0;if(T->lchild NULL && T->rchild NULL)return 1;elsereturn Leaves(T->lchild) Leaves(T->rchild…

服务器基础知识

服务器被誉为互联网之魂。我第一次见到服务器是在学校图书馆&#xff0c;是一种机架式服务器&#xff0c;第二次见到服务器是在公司机房。本期文章是对服务器进行大盘点和梳理&#xff0c;会介绍我拆装服务器过程&#xff0c;从中的学习感悟。 图片来自 Pexels 01 服务器 服务…

TCP网络常见名词

1、MAC地址 用来识别同一链路中不同的计算机。 2、IP地址 用来识别TCP/IP网络中互连的主机和路由器。 3、端口号 用来识别同一台计算机中进行通信的不同应用程序。 1&#xff09;端口号如何确定 <1>标准既定的端口号 它是指每个应用程序都有其指定的端口号。例如…

vue---消息订阅与发布(pubsub)

一种组件间通信的方式&#xff0c;适用于任意组件间通信 使用步骤&#xff1a; 安装pubsub&#xff1a;npm i pubsub-js 引入&#xff1a;import pubsub from pubsub-js 接收数据&#xff1a;A组件想接收数据&#xff0c;则在A组件中订阅消息&#xff0c;订阅的回调留在A组…

VSCode 开发C/C++实用插件分享——codegeex

VSCode 开发C/C实用插件分享——codegeex 一、codegeex 一、codegeex CodeGeeX 智能编程助手是一款编程插件&#xff0c;CodeGeeX支持多种主流IDE&#xff0c;如VS Code、IntelliJ IDEA、PyCharm、Vim等&#xff0c;同时&#xff0c;支持Python、Java、C/C、JavaScript、Go等多…

图片点击放大

在列表中添加插槽 <template slot-scope"scope">&#xff0c;获取当前点击的数据 在图片中添加点击事件的方法&#xff0c;用来弹出窗口 <vxe-columnfield"icon"title"等级图标"><template slot-scope"scope"><…

PyLMKit(3):基于角色扮演的应用案例

角色扮演应用案例RolePlay 0.项目信息 日期&#xff1a; 2023-12-2作者&#xff1a;小知课题: 通过设置角色模板并结合在线搜索、记忆和知识库功能&#xff0c;实现典型的对话应用功能。这个功能是大模型应用的基础功能&#xff0c;在后续其它RAG等功能中都会用到这个功能。功…

使用MD5当做文件的唯一标识,这样安全么?

使用MD5作为文件唯一标识符可靠么&#xff1f; 文章目录 使用MD5作为文件唯一标识符可靠么&#xff1f;什么是MD5&#xff1f;MD5的用途MD5作为文件唯一标识的优劣优势劣势 使用MD5作为文件唯一标识的建议其他文件标识算法结束语 什么是MD5&#xff1f; MD5&#xff08;Messag…

postman接口测试教程与实例分享

postman 的界面图 各个功能区的使用如下&#xff1a; 快捷区&#xff1a; 快捷区提供常用的操作入口&#xff0c;包括运行收藏夹的一组测试数据&#xff0c;导入别人共享的收藏夹测试数据&#xff08;Import from file, Import from folder, Import from link等&#xff09;&…

zookeeper心跳检测 (实操课程)

本系列是zookeeper相关的实操课程&#xff0c;课程测试环环相扣&#xff0c;请按照顺序阅读来学习和测试zookeeper。 阅读本文之前&#xff0c;请先阅读----​​​​​​zookeeper 单机伪集群搭建简单记录&#xff08;实操课程系列&#xff09;zookeeper 客户端常用命令简单记录…