设计模式学习(十八) 备忘录模式 Memento

1.备忘录模式的定义

不知道为什么这个星期要做很多事情,又好久没有学习了

 备忘录模式,这个模式的名字我总觉得起的不恰当,根据现代人的理解,似乎称之为存档/读档模式更好一点,毕竟备忘录对我来说,只是临时记录一下一些很重要的事情,但是这个模式本身却是标准的存档,然后觉得不行了获取存档的功能。所以我觉得对我个人而言,称其为存档/读档模式似乎更恰当一点。
 然后就是备忘录模式的官方定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后即可将该对象恢复到原先保存的状态。这个官方定义就是标准读/存档原理,很易于理解,不必细说了。

2.备忘录模式的类图

备忘录模式类图
 备忘录模式的类图很简单,Memento存档类为中间核心,Originator发布类与其呈依赖关系,Caretaker与其呈聚合关系,没有面向抽象类的编程过程。其中:

  1. Originator发布类:其存储所有表示其属性的信息State(一般情况下,这种内部属性数据会很多很多),然后有创建一个存档的函数CreateMemento,以及读取一个存档的函数SetMemento(其调用了Memento存档类的对象,故呈依赖关系)。
  2. Memento存档类:存档类中的数据,即为Originator发布类中的State数据。常规情况下,存档一旦存储了就不能更改,即只能读不能改。
  3. Caretaker管理员类:其用来管理Originator发布类所创建的存档,实现存档的增删读等操作。由于存档通常为多个,故其内部必然有存储这些存档的容器(故与Memento存档类呈聚合关系)。

3.备忘录模式的代码实现

 说到存档和读档,那想到的必然是游戏,本例中以著名波兰游戏TheWitcher3为Originator发布类(RPGgame),其底层系统TheWitcher3_System为Caretaker管理员类(RPGgame_System),其内部的存档为Memento类(SaveFile),根据上述类图实现了存档与读档的功能。
 本例实现的基本功能与标准类图基本一致,在此不做赘述,值得一提的是,本例中的存档名字采用当前系统 时间来判断,其中使用了windows.h文件。

#include <iostream>
#include <string>
#include <map>
#include <windows.h>
using namespace std;

string GetSystemTime()   //获取当前系统时间
{
	SYSTEMTIME m_time;
	GetLocalTime(&m_time);
	char szDateTime[100] = { 0 };
	sprintf_s(szDateTime, "%02d-%02d-%02d %02d:%02d:%02d", m_time.wYear, m_time.wMonth,
		m_time.wDay, m_time.wHour, m_time.wMinute, m_time.wSecond);
	string time(szDateTime);
	return time;
}

class SaveFile
{
public:
	SaveFile(int level, string mission, map<string, int> package, string savefilname)
	{
		sf_level = level;
		sf_mission = mission;
		sf_package = package;
		sf_savefilname = savefilname;
	}
	void ChangeSaveFile(int level, string mission, map<string, int> package)
	{
		sf_level = level;
		sf_mission = mission;
		sf_package = package;
	}
	string getName() 
	{
		return sf_savefilname;
	}
	map<string, int> getpackage()
	{
		return sf_package;
	}
	string getmission()
	{
		return sf_mission;
	}
	int getlevel()
	{
		return sf_level;
	}
private:
	int sf_level;
	string sf_mission;
	map<string, int> sf_package;
	string sf_savefilname;
};

class RPGgame
{
public:
	RPGgame(int level, string mission, map<string, int> package)
	{ 
		m_level = level;
		m_mission = mission;
		m_package = package;
	}
	SaveFile* CreateSaveFile()
	{
		return new SaveFile(m_level, m_mission, m_package, GetSystemTime());
	}
	void ChangeGame(int level, string mission, map<string, int> package)
	{
		m_level = level;
		m_mission = mission;
		m_package = package;
	}
	void LoadSaveFile(SaveFile* savefile)
	{
		m_level = savefile->getlevel();
		m_mission = savefile->getmission();
		m_package = savefile->getpackage();
	}
	void DisplaySaveFile()
	{
		cout << "m_level is " << m_level << endl;
		cout << "m_mission is " << m_mission << endl;
		for (auto &s : m_package)
			cout << s.first << " have " << s.second << endl;
	}
private:
	int m_level;
	string m_mission;
	map<string, int> m_package;
};

class RPGgameSystem
{
public:
	void InsertSaveFile(SaveFile* savefile)
	{
		m_savefile.insert({ savefile->getName(),savefile });
	}
	SaveFile* useSaveFile(string name)
	{
		return m_savefile.at(name);
	}
	void RemoveaveFile(string name)
	{
		m_savefile.erase(name);
	}
private:
	map<string, SaveFile*> m_savefile;
};

int main()
{
	RPGgameSystem* TheWitcher3_System = new RPGgameSystem;

	//用户数据的自定义
	map<string, int> Geralt_Package;
	Geralt_Package.insert({ "Memory Rose",1 });
	Geralt_Package.insert({ "Crystal Skulls",1 }); 

	//进入游戏读取默认存档
	RPGgame* TheWitcher3 = new RPGgame(10, "Kill Monster", Geralt_Package);

	//第一次存档
	cout << "***** TheWitcher3第一次存档 *****" << endl;
	SaveFile* savefile1 = TheWitcher3->CreateSaveFile();
	TheWitcher3_System->InsertSaveFile(savefile1);
	TheWitcher3->DisplaySaveFile();

	//第二次存档
	Sleep(1000);
	cout << "***** TheWitcher3第二次存档 *****" << endl;
	TheWitcher3->ChangeGame(12, "Find Child", Geralt_Package);
	SaveFile* savefile2 = TheWitcher3->CreateSaveFile();
	TheWitcher3_System->InsertSaveFile(savefile2);
	TheWitcher3->DisplaySaveFile();

	//第一次读档
	cout << "***** TheWitcher3第一次读档 *****" << endl;
	TheWitcher3->LoadSaveFile(TheWitcher3_System->useSaveFile(savefile1->getName()));
	TheWitcher3->DisplaySaveFile();

	//第二次读档
	cout << "***** TheWitcher3第二次读档 *****" << endl;
	TheWitcher3->LoadSaveFile(TheWitcher3_System->useSaveFile(savefile2->getName()));
	TheWitcher3->DisplaySaveFile();

	delete TheWitcher3_System;
	delete TheWitcher3;
	delete savefile1;
	delete savefile2;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值