栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

设计模式(行为型模式)(备忘录模式)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式(行为型模式)(备忘录模式)

备忘录模式

#include 
#include 

#ifdef _DEBUG   //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif

//#include 
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 m_pfmContainer; 
	};
	
}

int main()
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
	
	//第18章 备忘录(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)数据保存在内存中以及从内存中恢复数据。

	

	_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,恢复第一次快照,也就是恢复玩家生命值为800
	p_fighter2->restoreMomento(pfcaretaker2->getMemento(0));
	p_fighter2->displayInfo(); //玩家生命值应该恢复为800

	//释放资源
	delete p_fighter2;
	delete pfcaretaker2;
	return 0;
}

UML

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/784606.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号