设计模式之:备忘录模式

前言:

   这个国庆,回家不想学习,于是下了个三国志11,玩了好几天,终于从一个只有一个城池,5、6个武将,一两万士兵的刘备,发展成占有半壁江山了,灭了曹操,袁绍等,那在玩游戏的时候,我肯定不能连续几十个小时都不退出游戏,或者说不关机,那我每次肯定都需要保存游戏进度才能下次继续玩,那这就用上我这次要说的备忘录模式了,每次讲记录保存在存档里,下次进入游戏又可以接着上一次继续玩了~




定义(源于GoF《设计模式》)

在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

 如何实现这个将状态信息保存在某处呢?使用原型模式?由于对象通常封装了其部分或所有的状态信息,使得其状态不能被其他对象访问,也就不可能在该对象之外保存其状态了。由于原型模式总是返回对象的全部状态信息,同时原型模式使其状态能被其它对象访问,这样就违反了封装的原则,还可能有损应用的可靠性和可扩展性。
 
 一个备忘录是一个对象,它存储另一个对象在某个瞬间的所有状态,而后者称为备忘录的原发器。
 当需要设置原发器的检查点时,取消操作机制会向原发器请求一个备忘录。原发器用描述当前状态的信息初始化该备忘录。
 只有原发器可以向备忘录中存取信息,备忘录对其他的对象是“不可见”的。(通过友元来实现!)


关键点:

1、备份对象的状态;

2、不破坏封装!


UML图:(就如我所玩的游戏一样,一般游戏都有存档的限制,我这里设置了最多只能存档16个,当然每个都可以被覆盖!)


Memento:备忘录,用来存储原发器对象的内部状态。原发器根据需要决定备忘录存储原发器的哪些内部状态;防止原发器以外的其他对象访问备忘录。备忘录实际上有两个接口,管理者只能看到备忘录的窄接口————它只能将备忘录传递给其他对象。相反,原发器能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。理想的情况是只允许生成备忘录的那个原发器访问本备忘录的内部状态;
Originator:原发器,可创建一个备忘录,用以记录当前时刻它的内部状态;我们使用备忘录恢复内部状态;
Caretaker:负责保存备忘录;但是,不能对备忘录的内容进行操作或检查。

代码示例:

#include<iostream>
using namespace std;

class Memento              //备忘录中的原发器对象的内部状态
{

private:
	 friend class Originator;
	 Memento(int a,int b,int c):wujiangNum(a),chengchiNum(b),shibingNum(c){};
	int wujiangNum;     //武将数目
	int chengchiNum;	//城池数目
	int shibingNum;		//士兵数目

};

class Originator     //备忘录中的原发器,即需要备份的对象,利用Memento把对象的状态提取出来备份,而对象的函数方法等并不需要备份,只需备份状态
{
public:
	Originator()
	{

		this->wujiangNum=100;
		this->chengchiNum=100;
		this->shibingNum=100;


	};
	~Originator();
	void LoadState(Memento* memo){               //载入存档

		this->wujiangNum=memo->wujiangNum;
		this->chengchiNum=memo->chengchiNum;
		this->shibingNum=memo->shibingNum;


	}
	Memento* SaveState(){					//存档

		return new Memento(wujiangNum,chengchiNum,shibingNum);


	}

	void SometimeLater(){					//玩了一会之后,状态变化

		this->wujiangNum--;
		this->chengchiNum--;
		this->shibingNum--;


	}

	void showState(){					//展示状态

		cout<<this->wujiangNum<<endl<<this->chengchiNum<<endl<<this->shibingNum<<endl;

	}
private:
		int wujiangNum;     //武将数目
		int chengchiNum;	//城池数目
		int shibingNum;		//士兵数目


	/* data */
};


class Caretakerr  //备忘录模式中的,存档管理,就像游戏中的管理16个存档的对象
{
public:

	~Caretakerr()
	{


	};
	void SetStateMemento(Memento* pMemento,int index) { memento[index] = pMemento; }
	Memento *GetStateMemento(int index) { return memento[index] ; }

private:
	Memento* memento[16];

		/* data */
};




int main(int argc, char const *argv[])
{
	Originator* liubei=new Originator();//创建一个刘备
	Caretakerr pCaretaker;
	pCaretaker.SetStateMemento(liubei->SaveState(),1);       //存档到第一栏
	liubei->showState();

	liubei->SometimeLater();
	pCaretaker.SetStateMemento(liubei->SaveState(),2);      //一段时间后 存档到第二栏
	liubei->showState();

	liubei->LoadState(pCaretaker.GetStateMemento(1));		 //读取第一栏档
	liubei->showState();

	liubei->LoadState(pCaretaker.GetStateMemento(2));		 //读取第二栏档
	liubei->showState();

	liubei->SometimeLater();
	liubei->SometimeLater();
	pCaretaker.SetStateMemento(liubei->SaveState(),1);      //一段时间后 存档到第一栏
	liubei->LoadState(pCaretaker.GetStateMemento(1));		 //读取第一栏档
	liubei->showState();
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值