这是个人学习编程模式的系列学习笔记第十三篇。
采用Qt Creator进行编写,但尽量采用C++基础语法。
备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
比较典型的应用是过程中需要根据保存的数据,恢复之前的运行环境。比如游戏运行过程中保存当前进度,在需要的时候重新加载(比如打大Boss死掉了)。也可以是在做文本编辑时,撤销当前操作。
使用备忘录模式进行备份而不是使用Clone方法备份,主要有几个原因:
1、需要备份的东西并不是对象的全部
2、如果Clone,会形成一个新的对象,具有同样的行为(方法),不利于数据安全
3、不希望暴露备份对象的实现细节
场景描述
假设有一个简单的游戏,游戏主角有3个属性:血、金钱、战力。主角有多个行为。保存状态时保存主角的这三个状态。在需要恢复的时候,从保存的状态中重新加载主角状态恢复到之前状态。
设计思路
游戏主角类:三个属性(血、金钱、战力),四个行为(战斗、花钱、保存状态、重载状态)。
状态存储类:三个属性,血、金钱和战力。
状态管理类:负责状态对象的管理,不能接触具体的状态存储等细节。
UML
代码
#include <iostream>
using namespace std;
class Status
{
public:
int m_blood;
int m_money;
int m_force;
public:
Status(int blood, int money, int force):m_blood(blood),m_money(money),m_force(force) {}
};
class Role
{
private:
int m_blood;
int m_money;
int m_force;
public:
Role(int blood, int money, int force):m_blood(blood),m_money(money),m_force(force) {}
void buy() {if(m_money > 0) m_money--;}
void attack() {if(m_blood > 0) {m_blood--; m_force++;}}
void displayStatus()
{
cout<<"Blood: "<<m_blood<<"\n";
cout<<"Money: "<<m_money<<"\n";
cout<<"Force: "<<m_force<<"\n";
}
Status* saveStatus()
{
return new Status(m_blood, m_money, m_force);
}
bool reload(Status* status)
{
m_blood = status->m_blood;
m_money = status->m_money;
m_force = status->m_force;
return true;
}
};
class StatusCaretaker
{
private:
Status* m_status = 0;
public:
void setStatus(Status* status) {m_status = status;}
Status* getStatus() {return m_status;}
~StatusCaretaker() {delete m_status;}
};
int main()
{
Role* role = new Role(10, 20, 30);
StatusCaretaker* caretaker = new StatusCaretaker();
cout<<"The role\'s status: \n";
cout<<"Initial status:\n";
role->displayStatus();
caretaker->setStatus(role->saveStatus());
role->buy();
role->attack();
cout<<"After buy and attack:\n";
role->displayStatus();
role->reload(caretaker->getStatus());
cout<<"Reload status:\n";
role->displayStatus();
delete caretaker;
delete role;
return 0;
}