备忘录模式
这个模式让我首先联想到的就是游戏存档,打boss或者不玩的时候,存个档,之后读档接着玩。而存档就相当于将数据存储到该存储的地方,而读档就是把数据读取出来。大部分游戏都是HP、MP、攻击力和生命值,而从开发角度看,你角色本身具有这些属性,而存档时存的数据也需要存储这些属性,这就相当于有一个模板,里面都是各种数据,然后你的角色拷贝了一份,然后显示出来;而存档,经常存到第三方,如文件、数据库等等。存档、读档的操作是角色(玩家)所具备的一个功能,所以存档就是角色提供一个方法,把自身的数据输入到存档模板里面,然后放到该放的地方去,而备忘录模式,就是不破坏数据和封装性的前提下,将一个对象(角色)的内部状态进行外部存储,并且可以回复存储时的状态。
Originator:就是你所控制的角色对象,存储许多数据,比如血量等等,并且需要提供save和load两个接口,以便进行存档和读档操作,而且在游戏进行过程中,这个对象就是进行个中交互的对象,比如血量增加等等
Memento:存储模板,简单来说就是数据存储的临时对象(对象某个情况下的内部状态),当你存档的时候,会将需要存档的数据写到一个该对象中,然后通过服务器或者管理系统,将该对象存储到该存储的地方
Caretaker:管理者,负责保存备忘录,不可对其内容进行修改或检查,简单来说就是游戏公司不可随意修改存档。
使用场景:
- 需要保存和回复数据的场景
- 提供回滚或者上一步、上几步的功能
优点:
- 提供回档机制,避免失误操作
- 实现数据封装,用户不需要了解存档和读档细节
缺点:
- 保存的数据几乎时克隆出一个独立数据,大部分时间存储在内存中,如果数据过大,可能造成内存过高
实操
注:在实现的过程中,可以认为的区分一些临时和存档数据,这样在存档数据的类中可能就可以减少一些数据的存储。
思维实现:
- 设计实现CSaveData数据模板,先实现该类,确定需要存储的数据
- 实现角色类,将所有需要显示或者使用到的数据存储进行定义
- 实现Save和Read函数,将需要存储的数据进行存档和读档操作
- 实现管理类,管理类只能负责存储和读取数据,没有外部接口可以操作和检查数据
// MemorandumModel.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
//存档数据
class CSaveData
{
private:
int m_healthPoint;
int m_manaPoint;
int m_attackValue;
int m_defenseValue;
public:
CSaveData() {}
CSaveData(int health, int mana, int attack, int defense)
{
m_healthPoint = health;
m_manaPoint = mana;
m_attackValue = attack;
m_defenseValue = defense;
}
int getHealthPoint() { return m_healthPoint; }
void setHealthPoint(int value) { m_healthPoint = value; }
int getManaPoint() { return m_manaPoint; }
void setManaPonit(int value) { m_manaPoint = value; }
int getAttackValue() { return m_attackValue; }
void setAttackValue(int value) { m_attackValue = value; }
int getDefenseValue() { return m_defenseValue; }
void setDefenseValue(int value) { m_defenseValue = value; }
};
class CRole
{
private:
int m_healthPoint;
int m_manaPoint;
int m_attackValue;
int m_defenseValue;
public:
CRole()
{
m_healthPoint = 100;
m_manaPoint = 100;
m_attackValue = 10;
m_defenseValue = 10;
}
//
//....数值set和get
//
void setHealthPoint(int value) { m_healthPoint = value; }
//存档
CSaveData* saveRoleData()
{
return new CSaveData(m_healthPoint, m_manaPoint, m_attackValue, m_defenseValue);
}
//读档
void readRoleData(CSaveData* data)
{
m_healthPoint = data->getHealthPoint();
m_manaPoint = data->getManaPoint();
m_attackValue = data->getAttackValue();
m_defenseValue = data->getDefenseValue();
}
//
void show()
{
cout << "HP :"<<m_healthPoint<<endl;
cout << "MP :"<<m_manaPoint<<endl;
cout << "Attack :"<<m_attackValue<<endl;
cout << "Defense:"<<m_defenseValue<<endl;
}
};
class CRoleDataManager
{
private:
CSaveData* m_roleData;
public:
CSaveData* getSaveData() { return m_roleData; }
void setSaveData(CSaveData* data) { m_roleData = data; }
};
int main()
{
CRole *role = new CRole();
cout << "=============初始状态====================" << endl;
role->show();
//保存
CRoleDataManager* data = new CRoleDataManager();
data->setSaveData(role->saveRoleData());
//升级
role->setHealthPoint(1000);
cout << "=============升级了,属性变化:==========" << endl;
role->show();
//回档
role->readRoleData(data->getSaveData());
cout << "============开挂,被回档=================" << endl;
role->show();
}