c/c++设计模式--备忘录模式

news/2024/10/3 10:36:59
#include <iostream>
#include <vector>#ifdef _DEBUG   //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996) namespace _nmsp1
{    //玩家主角相关的备忘录类class FighterMemento{private://构造函数,用private修饰以防止在外部被随意创建FighterMemento(int life,int magic,int attack):m_life(life), m_magic(magic), m_attack(attack) {}private://提供一些供Fighter类访问的接口,用private修饰防止被任意类访问friend class Fighter; //友元类Fighter可以访问奔雷的私有成员函数int getLife() const { return m_life; }void setLife(int life) { m_life = life; }int getMagic() const { return m_magic; }void setMagic(int magic) { m_magic = magic; }int geAttack() const { return m_attack; }void setAttack(int attack) { m_attack = attack; }private://玩家主角类中要保存起来的数据,就放到这里来int m_life; //生命值int m_magic; //魔法值int m_attack; //攻击力
    };//玩家主角类class Fighter{public://构造函数Fighter(int life, int magic, int attack) :m_life(life), m_magic(magic), m_attack(attack) {}public://将玩家数据写入备忘录(创建备忘录,并在其中存储了当前状态)FighterMemento* createMomento(){return new FighterMemento(m_life, m_magic, m_attack);}//从备忘录中恢复玩家数据void restoreMomento(FighterMemento* pfm){m_life = pfm->getLife();m_magic = pfm->getMagic();m_attack = pfm->geAttack();}//为测试目的引入的接口,设置玩家的生命值为0(玩家死亡)void setToDead(){m_life = 0;}//用于输出一些信息void displayInfo(){cout << "玩家主角当前的生命值、魔法值、攻击力分别为:" << m_life << "," << m_magic << "," << m_attack << endl;}private://角色属性int m_life; //生命值int m_magic; //魔法值int m_attack; //攻击力//.....其他数据略
    };//管理者(负责人)类class FCareTaker{public://构造函数FCareTaker(FighterMemento* ptmpfm) :m_pfm(ptmpfm) {} //形参是指向备忘录对象的指针//获取指向备忘录对象的指针FighterMemento* getMemento(){return m_pfm;}//保存指向备忘录对象的指针void setMemento(FighterMemento *ptmpfm){m_pfm = ptmpfm;}private:FighterMemento* m_pfm; //指向备忘录对象的指针
    };//------------------------//支持多个快照的负责人(管理者)类class FCareTaker2{public://析构函数用于释放资源~FCareTaker2(){for (auto iter = m_pfmContainer.begin(); iter != m_pfmContainer.end(); ++iter){delete (*iter);}}//保存指向备忘录对象的指针void setMemento(FighterMemento* ptmpfm){m_pfmContainer.push_back(ptmpfm);}//获取指向备忘录对象的指针FighterMemento* getMemento(int index){auto iter = m_pfmContainer.begin();for (int i = 0; i <= index; ++i){if (i == index)return (*iter);else++iter;}return NULL;}private://存储备忘录对象指针的容器vector<FighterMemento*> m_pfmContainer; };}int main()
{_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口/*_nmsp1::Fighter* p_fighter = new _nmsp1::Fighter(800, 200, 300);//(1)显示玩家主角在与BOSS战斗之前的信息p_fighter->displayInfo();//(2)为玩家主角类对象创建一个备忘录(其中保存了当前主角类对象中的必要信息)//_nmsp1::FighterMemento* p_fighterMemo = p_fighter->createMomento();_nmsp1::FCareTaker* pfcaretaker = new _nmsp1::FCareTaker(p_fighter->createMomento());//(3)玩家与BOSS开始战斗cout << "玩家主角与BOSS开始进行激烈的战斗-------" << endl;p_fighter->setToDead(); //玩家主角在与BOSS战斗中,生命值最终变成0而死亡(被BOSS击败)p_fighter->displayInfo(); //显示玩家主角在与BOSS战斗之后的信息//(4)因为在与BOSS战斗之前已经通过NPC保存了游戏进度,这里模拟载入游戏进度,恢复玩家主角类对象的数据,让其可以与BOSS再次战斗cout << "玩家主角通过备忘录恢复自己的信息------" << endl;//p_fighter->restoreMomento(p_fighterMemo);p_fighter->restoreMomento(pfcaretaker->getMemento());p_fighter->displayInfo(); //显示玩家主角通过备忘录恢复到战斗之前的信息//(5)释放资源//delete p_fighterMemo;delete pfcaretaker->getMemento();delete pfcaretaker; delete p_fighter;*/_nmsp1::Fighter* p_fighter2 = new _nmsp1::Fighter(800, 200, 300);_nmsp1::FCareTaker2* pfcaretaker2 = new _nmsp1::FCareTaker2();pfcaretaker2->setMemento(p_fighter2->createMomento()); //做第一次快照,此快照玩家生命值为800。p_fighter2->setToDead(); //改变玩家主角的生命值pfcaretaker2->setMemento(p_fighter2->createMomento());//做第二次快照,此快照玩家生命值为0。p_fighter2->displayInfo(); //玩家主角生命值应为为0.cout << "----------------" << endl;//当前玩家生命值为0,恢复第一次快照,也就是恢复玩家生命值为800p_fighter2->restoreMomento(pfcaretaker2->getMemento(0));p_fighter2->displayInfo(); //玩家生命值应该恢复为800//释放资源delete p_fighter2;delete pfcaretaker2;return 0;
}

备忘录(Memento)模式:快照模式(Snapshot),行为型模式。
//(1)一个具体实现范例
// 一般该模式还会引入一个 管理者(负责人)类,但是这并不是必须的。 FCareTaker

//(2)引入备忘录(Memento)模式
//定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,
//这样以后就可以将该对象恢复到原先保存的状态
//3种角色
//a)Originator(原发器):Fighter类。
//b)Memento(备忘录):FighterMemnto类。
//c)CareTaker(负责人/管理者):FCareTaker类。
//备忘录真正的作用并不是保存数据,而是恢复数据。

//说明:

//a)快照——并不意味着所有玩家主角类的信息都要往备忘录中保存。
//b)做快照并不要求玩家主角类中需要保存的字段都一一对应备忘录中相同的字段,备忘录中可以以
//内存流,字符串,编码(Hex编码、Base64编码)方式存储或者还原来自玩家主角类中的数据。
//数据序列化。
//c)给玩家主角类做快照并不仅仅限于一次。FCareTaker2做多次快照。给了一个范例
//d)friend
//e)更适合保存原发器对象中的一部分(不是所有)内部状态,否则采用原型模式。
//f)优点:方便回到一个特定的历史步骤。缺点:对资源的消耗。
//g)完全存储。增量存储来应付频繁做快照。 完全存储和增量存储方式结合使用。Redis,RDB(完全备份),AOF(增量备份)。
//减少需要记录的数据。
//h)应用场合:下棋悔棋,保存历史记录,做快照。
//i)数据保存在内存中以及从内存中恢复数据。

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

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

相关文章

超级底层:10WQPS/PB级海量存储HBase/RocksDB,底层LSM结构是什么?

文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,…

运筹学练习Python精解——动态规划

练习1 设国家拨给60万元投资,供四个工厂扩建使用,每个工厂扩建后的利润与投资额的大小有关,投资后的利润函数如下表所示,试给出收益最大的投资计划。利润\投资 0 10 20 30 40 50 60\(g_1(r)\) 0 20 50 65 80 85 85\(g_2(x)\) 0 20 40 50 55 60 65\(g_3(x)\) 0 25 60 85 100…

基本技巧——哈夫曼树 学习笔记

基本技巧——哈夫曼树 学习笔记基本技巧——哈夫曼树 学习笔记 概念 一棵包含有 \(n\) 个叶子节点的 \(k\) 叉树,其中第 \(i\) 个叶子节点带有权值 \(W_i\)。 树的带权路径长度,定义为从根结点到各叶结点的路径长度与相应叶节点权值的乘积之和。 树的带权路径长度,记为 WPL(…

盘点 Spring Boot 解决跨域请求的几种办法

熟悉 web 系统开发的同学,对下面这样的错误应该不会太陌生。之所以会出现这个错误,是因为浏览器出于安全的考虑,采用同源策略的控制,防止当前站点恶意攻击 web 服务器盗取数据。 01、什么是跨域请求 同源策略,简单的说就是当浏览器访问 web 服务器资源时,只有源相同才能正…

基于正点原子ZYNQ7020的RTSP摄像头视频流获取

记录如何修改,编译定制化petalinux镜像,实现PS端和PL端互通硬件描述 硬件需求ZYNQ7020 系列 LCD 显示屏 800*600rtsp 网口摄像头接线方式USB_UART 通过 type-c 线连接电脑,电脑需要安装 CH340 的串口驱动 ps 端网口和摄像头的网口连接 开发板和摄像头的电源线连接 LCD 显示屏的…

移动平台开发综合实践 安卓android大作业-雷net在线对战

转自我的安卓课程作业 图片应该是没了,懒得搞了目录移动平台开发综合实践 大作业-雷net在线对战一、实验目的二、实验环境三、实验内容与实验要求3.1实验内容:雷net在线对战3.1.1棋盘3.1.2棋子3.1.3终端卡3.2原理分析3.3具体实验要求四、实验过程与分析4.1实验记录4.1.1 Sock…

解析Html Canvas的卓越性能与高效渲染策略

一、什么是Canvas 想必学习前端的同学们对Canvas 都不陌生,它是 HTML5 新增的“画布”元素,可以使用JavaScript来绘制图形。 Canvas元素是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。Canvas 由…

怎么控制多个存储设备的访问权限?数据安全存储方案来了

数据安全存储是指将数据以安全的方式存储在存储系统中,以确保数据的机密性、完整性和可用性。要控制数据安全存储的权限以保障安全,可以采取以下措施:访问控制列表(ACLs):使用ACLs来定义对存储数据的访问权限。ACLs允许你为每个文件或目录指定哪些用户或组有权访问它们,…