C++ 设计模式之备忘录模式

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【设计模式大纲】


【简介】

        -- 什么是备忘录模式 (第17种模式)

        备忘录模式(Memento Pattern)是⼀种⾏为型设计模式,它允许在不暴露对象实现的情况下捕获对象的内部状态并在对象之外保存这个状态,以便稍后可以将其还原到先前的状态。


【基本结构】

        备忘录模式包括以下⼏个重要⻆⾊:

  • 发起⼈Originator : 需要还原状态的那个对象,负责创建⼀个【备忘录】,并使⽤备忘录记录当前时刻的内部状态。
  • 备忘录Memento : 存储发起⼈对象的内部状态,它可以包含发起⼈的部分或全部状态信息,但是对外部是不可⻅的,只有发起⼈能够访问备忘录对象的状态。

        备忘录有两个接⼝,发起⼈能够通过宽接⼝访问数据,管理者只能看到窄接⼝,并将备忘录传递给其他对象。

  • 管理者Caretaker : 负责存储备忘录对象,但并不了解其内部结构,管理者可以存储多个备忘录对象。
  • 客户端:在需要恢复状态时,客户端可以从管理者那⾥获取备忘录对象,并将其传递给发起⼈进⾏状态的恢复。


【基本实现】

下面以Java代码作以简要说明:

1. 创建发起⼈类:可以创建备忘录对象

class Originator {private String state;public void setState(String state) {this.state = state;}public String getState() {return state;}// 创建备忘录对象public Memento createMemento() {return new Memento(state);}// 通过备忘录对象恢复状态public void restoreFromMemento(Memento memento) {state = memento.getState();}
}

2. 创建备忘录类:保存发起⼈对象的状态

class Memento {private String state;// 保存发起⼈的状态public Memento(String state) {this.state = state;}public String getState() {return state;}
}

3. 创建管理者:维护⼀组备忘录对象

class Caretaker {private List<Memento> mementos = new ArrayList<>();public void addMemento(Memento memento) {mementos.add(memento);}public Memento getMemento(int index) {return mementos.get(index);}
}

4. 客户端使用备忘录模式

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file MementoMode.hpp
* @brief 备忘录模式
* @autor 写代码的小恐龙er
* @date 2024/01/19
*/
public class Main {public static void main(String[] args) {// 创建发起⼈对象Originator originator = new Originator();originator.setState("State 1");// 创建管理者对象Caretaker caretaker = new Caretaker();// 保存当前状态caretaker.addMemento(originator.createMemento());// 修改状态originator.setState("State 2");// 再次保存当前状态caretaker.addMemento(originator.createMemento());// 恢复到先前状态originator.restoreFromMemento(caretaker.getMemento(0));System.out.println("Current State: " + originator.getState());}
}

【使用场景】

        备忘录模式在保证了对象内部状态的封装和私有性前提下可以轻松地添加新的备忘录和发起⼈,实现“备份”,不过备份对象往往会消耗较多的内存,资源消耗增加。

        备忘录模式常常⽤来实现撤销和重做功能,⽐如在Java Swing GUI编程中,javax.swing.undo 包中的撤销(undo)和重做(redo)机制使⽤了备忘录模式。UndoManager 和UndoableEdit 接⼝是与备忘录模式相关的主要类和接⼝。


【C++编码部分】

1. 题目描述

        小明正在设计一个简单的计数器应用,支持增加(Increment)和减少(Decrement)操作,以及撤销(Undo)和重做(Redo)操作,请你使用备忘录模式帮他实现。

2. 输入描述

        输入包含若干行,每行包含一个字符串,表示计数器应用的操作,操作包括 "Increment"、 "Decrement"、"Undo" 和 "Redo"。

3. 输出描述

        对于每个 "Increment" 和 "Decrement" 操作,输出当前计数器的值,计数器数值从0开始 对于每个 "Undo" 操作,输出撤销后的计数器值。 对于每个 "Redo" 操作,输出重做后的计数器值。

4. C++编码实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file MementoMode.hpp
* @brief 备忘录模式
* @autor 写代码的小恐龙er
* @date 2024/01/19
*/#include <iostream>
#include <string>
#include <vector>
#include <stack>using namespace std;// 前置声明// 备忘录类 -- 保存发起⼈对象的状态
class Memento;
// 发起人类 -- 可以创建备忘录对象
class Counter;
// 管理者 -- 一组备忘录对象
class MementoManager;// 类的定义// 备忘录类
class Memento
{
// 成员数据
private:int _value;// 备忘录操作的成员函数
public:Memento(int value){SetValue(value);}void SetValue(int value){this->_value = value;}int GetValue(){return this->_value;}
};// 发起人 类
class Counter
{
// 成员数据
private:int _value;//  发起人的计数值std::stack<Memento *> _undoStack; // 发起人撤销操作的栈 std::stack<Memento *> _redoStack; // 发起人重新操作的栈// 成员函数 
public:Counter(){}// 获取值int GetValue(){return this->_value;}// 增加计数值void IncreaseValue(Memento *memento){//清空重做的栈while(!_redoStack.empty()){_redoStack.pop();}_undoStack.push(memento);_value++;}// 减少计数值void DecreaseValue(Memento *memento){//清空重做的栈while(!_redoStack.empty()){_redoStack.pop();}_undoStack.push(memento);_value--;}// 撤销操作void Undo(Memento *memento){if(!_undoStack.empty()){_redoStack.push(memento);_value = _undoStack.top()->GetValue();}}// 重新操作void Redo(Memento *memento){if(!_redoStack.empty()){_undoStack.push(memento);_value = _redoStack.top()->GetValue();}}
};// 管理者 
class MementoManager
{
// 成员数据
private:std::vector<Memento *> _mementoVec;// 成员函数
public:// 增加备忘录void AddMemento(Memento *mento){_mementoVec.push_back(mento);}// 寻找备忘录 按照顺序 或者 备忘录中的计数值Memento * GetMemento(int index){if(index >= _mementoVec.size()) return nullptr;else return _mementoVec[index];}
};// 客户端
int main()
{// 操作类型string type = "";// 新建 发起人 类 Counter *counter = new Counter();// 新建备忘录管理者MementoManager *manager = new MementoManager();// 新建备忘录Memento *memento = nullptr;// 等待输入指令while(std::cin >> type){if(type == "Increment"){memento = new Memento(counter->GetValue());counter->IncreaseValue(memento);}else if(type == "Decrement"){memento = new Memento(counter->GetValue());counter->DecreaseValue(memento);}else if(type == "Undo"){memento = new Memento(counter->GetValue());counter->Undo(memento);}else if(type == "Redo"){memento = new Memento(counter->GetValue());counter->Redo(memento);}// 将备忘录添加至管理者中 【此时备忘录管理者可以去做其他的事情】manager->AddMemento(memento);// 输出计数器的值std::cout<< counter->GetValue() << endl;}// 析构if(memento != nullptr){delete memento;memento = nullptr;}delete counter;counter = nullptr;delete manager;manager = nullptr;return 0;
}


......

To be continued.

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

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

相关文章

【C语言】- 设置控制台标题、编码、文字颜色、大小和字体

【C语言】- 设置控制台标题、编码、文字颜色、大小和字体 文章目录 【C语言】- 设置控制台标题、编码、文字颜色、大小和字体1 - 设置控制台标题2 - 设置控制台编码3 - 设置控制台字体和大小参考链接 1 - 设置控制台标题 因为要用到 Windows API&#xff0c;所以需要包含头文件…

UI组件在线预览,程序员直呼“不要太方便~”

一、介绍 以往大家如果想查看组件的使用效果&#xff0c;需要打开DevEco Studio构建工程。现在为了便于大家高效开发&#xff0c;文档上线了JS UI组件在线预览功能&#xff0c;无需本地构建工程&#xff0c;在线即可修改组件样式等参数、一键预览编译效果。程序员直呼&#xff…

可视化k8s页面(Kubepi)

Kubepi是一个简单高效的k8s集群图形化管理工具&#xff0c;方便日常管理K8S集群&#xff0c;高效快速的查询日志定位问题的工具 随便在哪个节点部署&#xff0c;我这里在主节点部署 docker pull kubeoperator/kubepi-server docker run --privileged -itd --restartunless-st…

RabbitMQ-生产者可靠性

一、生产者重连 1、概念 由于网络波动导致客户端无法连接上MQ&#xff0c;这是可以开启MQ的失败后重连机制。 注意&#xff1a; 是连接失败的重试&#xff0c;而不是消息发送失败后的重试。 2、开启配置 spring:rabbitmq:template:retry:enabled: true # 是否启用重试机制ma…

【RabbitMQ】RabbitMQ安装与使用详解以及Spring集成

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《RabbitMQ实战》。&#x1f3af;&#x1f3af; &am…

java实现红黑树

红黑树 红黑树是一种自平衡二叉查找树&#xff0c;其中每个节点都有一个颜色属性&#xff0c;颜色为红色或黑色。它的特性保证了树在插入和删除操作后仍然保持大致的平衡&#xff0c;使得查找操作能够在对数时间内完成。以下是红黑树的一些基本性质&#xff1a; 每个节点是红…

面试题16.15.珠玑妙算

前言 这两天突然发现力扣上还是有我能写出来的题的&#xff0c;虽说都是简单级别的&#xff08;以及一道中等的题&#xff09;&#xff0c;但是能写出来力扣真的太开心了&#xff0c;&#xff08;大佬把我这段话当个玩笑就行了&#xff09;&#xff0c;于是乎&#xff0c;我觉…

C#,入门教程(21)——命名空间(namespace)与程序结构的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(20)——列表&#xff08;List&#xff09;的基础知识https://blog.csdn.net/beijinghorn/article/details/124094382 编写软件&#xff08;大软件称为系统&#xff09;与盖大楼一个道理。 假设咱们现在需要盖一座名为“天梯大厦”的…

kubernetes工作负载-DamonSet

一、DemonSet的介绍 1、什么是DemonSet DaemonSet 控制器是用来保证在所有节点上运行一个 Pod 的副本当有节点加入集群时&#xff0c; 也会为他们新增一个 Pod。 当有节点从集群移除时&#xff0c;这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 简而言之…

进入docker容器,vi: command not found

问题描述&#xff1a; 进入docker容器&#xff0c;查看文件执行vim 命令&#xff0c;报错 vim: command not found。搜索解决方案&#xff0c;说执行一下 apt-get install vim命令&#xff0c;然后又报错 Unable to locate package vim。 解决&#xff1a; 1.执行 npt-get up…

YOLOv3:算法与论文详细解读

【yolov1&#xff1a;背景介绍与算法精讲】 【yolo9000&#xff1a;Better, Faster, Stronger的目标检测网络】 目录 一、YOLOv3概述二、创新与改进三、改进细节3.1 多尺度特征3.2 不同尺度先验框3.3 完整的网络结构3.3 Darknet-53主干网络3.4 残差网络3.4.1 恒等映射3.4.2 网络…

git提交代码到远端仓库的方法详解

一、何为git git就是版本控制器&#xff0c;就比如说你新建了一个git文件夹&#xff0c;里面用于存放你的C语言实习报告&#xff0c;现在要用git对该文件夹进行接管。当你修改了你的C语言实习报告点击保存之后&#xff0c;就用git的相关命令&#xff0c;提交给git&#xff0c;让…

go语言(十)---- 面向对象封装

面向对象的封装 package mainimport "fmt"type Hero struct {Name stringAd intLevel int }func (this Hero) Show(){fmt.Println("Name ", this.Name)fmt.Println("Ad ", this.Ad)fmt.Println("Level ", this.Level)}func (thi…

priority_queue的使用与模拟实现(容器适配器+stack与queue的模拟实现源码)

priority_queue的使用与模拟实现 引言&#xff08;容器适配器&#xff09;priority_queue的介绍与使用priority_queue介绍接口使用默认成员函数 size与emptytoppush与pop priority_queue的模拟实现构造函数size与emptytoppush与pop向上调整建堆与向下调整建堆向上调整建堆向下调…

个人实现的QT拼图游戏(开源),QT拖拽事件详解

文章目录 效果图引言玩法 拖拽概念基本概念如何在Qt中使用拖放注意事项 游戏关键问题总结 效果图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c6dd66befd314442adf07e1dec0d550c.png 引言 在学习QT demo时&#xff0c;发现有一个拼图demo&#xff0c;介绍拖…

【算法Hot100系列】跳跃游戏

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

Linux搭建dns主从服务器

一、实验要求 配置Dns主从服务器&#xff0c;能够实现正常的正反向解析 二、知识点 1、DNS简介 DNS&#xff08;Domain Name System&#xff09;是互联网上的一项服务&#xff0c;它作为将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互联网。…

磁的基本知识

磁的基本知识。 一、磁铁及其基本性质。 1、磁铁的概念。 具有吸引铁、钴、镍等金属能力的物质叫做磁体&#xff0c;俗称磁铁、吸铁石。被吸引的铁、钴、镍等物质叫做铁磁性材料。磁铁吸引铁磁性材料的性质叫做磁性。 2、磁铁的分类。 磁铁可分为天然磁铁和人造磁铁两种。天然…

准备注销CSDN了,再也不用了

动不动就是“外包干了2个月&#xff0c;技术明显…”推荐在首页&#xff0c;看到就烦&#xff0c;彻彻底底的垃圾堆&#xff0c;一个相同的标题滑不到底&#xff0c;点进去就是面试题、推销&#xff0c;牛头不对马嘴&#xff0c;真垃圾&#xff08;画个圈圈&#xff09;&#x…

postman导入https证书

进入setting配置中Certificates配置项 点击“Add Certificate”,然后配置相关信息 以上配置完毕&#xff0c;如果测试出现“SSL Error:Self signed certificate” 则将“SSL certificate verification”取消勾选