背景:游戏打boss前存档。一种保存在磁盘,一种保存在内存如网页等。
1.游戏角色类有生命力,攻击力,防御值,以及显示,初始状态,战斗函数(参数均设为0)。(set get)
客户端(main函数)保存进度,重新定义一个对象将改对象一一赋值过去。恢复即将备份的对象赋值过去。但暴漏了接口和细节。若新增魔法力也不容易修改
备忘录模式(memento)
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象状态恢复到原先保存的状态。
UML结构图
将保存的细节封装在Memento之中了,哪一天要更改保存的细节也不用影响客户端了。
2.适用:Memento模式比较适合功能比较复杂的,但需要维护或者记录属性历史的类,或者需要保存的属性只是众多属性中的一部分时,Originator可以根据保存的Memento信息还原到前一状态。(命令模式也有类似的功能)
如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。有时一些对象的内部信息必须保存在对象以外的地方,但是必须要由对象自己读取,这时使用备忘录模式可以把复杂的对象内部信息对其它的对象屏蔽起来,从而可以恰当的保持封装的边界。
最大的作用当角色的状态改变时,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
c++ 代码实现
//角色状态存储箱类
class RoleStateMemento {
private:
int m_mp;
int m_hp;
public:
RoleStateMemento(int a, int b) //将HP MP存入状态箱对象中
{
this->m_hp = a;
this->m_mp = b;
}
void seHp(int a) { m_hp = a; }
void seMp(int a) { m_mp = a; }
int getHp() { return m_hp; }
int getMp() { return m_mp; }
};
//游戏角色类
class GameRole {
private:
int m_mp;
int m_hp;
public:
GameRole()
{
m_mp = 100;
m_hp = 100;
}
//保存角色状态,将游戏角色的状态通过实例化“角色状态存储箱类” 返回
RoleStateMemento * SaveState()
{
return new RoleStateMemento(m_mp, m_hp);
}
//恢复角色状态 将外部的角色状态存储箱中的状态恢复给游戏角色
void RecoverState(RoleStateMemento* m)
{
m_hp = m->getHp();
m_mp = m->getMp();
}
void flight()
{
m_hp = 1;
m_mp = 1;
}
void show()
{
cout << "hp:" << m_hp << endl;
cout << "mp:" << m_mp << endl;
}
};
//角色状态管理者类
class RoleStateMementoManage {
private:
RoleStateMemento* m_state;
public:
void setRoleStateMemento(RoleStateMemento* m)
{
m_state = m;
}
RoleStateMemento* getRoleStateMemento()
{
return m_state;
}
};
int main()
{
std::cout << "Hello World!\n";
//打boss前
GameRole* gr = new GameRole();
gr->show();
//保存进度
RoleStateMementoManage* rm = new RoleStateMementoManage();
rm->setRoleStateMemento(gr->SaveState());
//大战boss;
gr->flight();
gr->show();
//恢复
gr->RecoverState(rm->getRoleStateMemento());
gr->show();
}
缺点:角色状态要完整存储到备忘录对象中,如果状态数据很大很多,将会非常消耗内存。