前言
今天复习了备忘录模式,感觉挺简单的,这里给大家分享下。
1. 备忘录模式的理解
备忘录模式,就是将对象中的部分或全部数据抽离出来,在另外一个用作备份的类中存储起来,当需要时再从这个备份类中恢复,封装备份与恢复细节。
备忘录模式的定义与类图(引用《大话设计模式》)如下所示:
2. 备忘录模式 C++实现
这里以备份游戏进度为例,实现备忘录模式。
备份游戏进度的类图(引用《大话设计模式》)如下:
上述例子的C++实现如下:
#include <iostream>
#include <memory>
//*****************Memo Pattern*****************
//备忘录类
class GameRoleMemento
{
private:
int vit;
int atk;
int def;
public:
GameRoleMemento(const int nVit, const int nAtk, const int nDef) : vit(nVit), atk(nAtk), def(nDef) {}
int GetVit() const
{
return vit;
}
int GetAtk() const
{
return atk;
}
int GetDef() const
{
return def;
}
};
//管理备忘录类
class RoleStateCaretaker
{
private:
std::shared_ptr<GameRoleMemento> smartMemento;
public:
void SetGameRoleMemento(std::shared_ptr<GameRoleMemento> pMemento)
{
smartMemento = pMemento;
}
std::shared_ptr<GameRoleMemento> GetGameRoleMemento() const
{
return smartMemento;
}
};
//游戏角色类
class GameRole
{
private:
int vit;//生命力
int atk;//攻击力
int def;//防御力
public:
GameRole(int nVit, int nAtk, int nDef) : vit(nVit), atk(nAtk), def(nDef) {}
GameRoleMemento* SaveState()
{
return new GameRoleMemento(vit, atk, def);
}
void DisplayState()
{
std::cout << "当前生命力:" << vit << ", 当前攻击力:" << atk << ", 当前防御力:" << def << std::endl;
}
void RecoveryState(const GameRoleMemento& memento)
{
vit = memento.GetVit();
atk = memento.GetAtk();
def = memento.GetDef();
}
void Fight()
{
vit = 0;
atk = 0;
def = 0;
}
};
//********************Test********************
int main()
{
std::cout << "大战Boss前" << std::endl;
std::shared_ptr<GameRole> lixiaoyao = std::make_shared<GameRole>(100, 100, 100);
lixiaoyao->DisplayState();
//保存进度
std::shared_ptr<RoleStateCaretaker> stateAdmin = std::make_shared<RoleStateCaretaker>();
stateAdmin->SetGameRoleMemento(std::shared_ptr<GameRoleMemento>(lixiaoyao->SaveState()));
std::cout << "\n大战后" << std::endl;
lixiaoyao->Fight();
lixiaoyao->DisplayState();
std::cout << "\n恢复到大战前:" << std::endl;
lixiaoyao->RecoveryState(*(stateAdmin->GetGameRoleMemento()));
lixiaoyao->DisplayState();
system("pause");
return 0;
}
总结
备忘录模式的优点是客户端不需要了解备份与还原的细节,只要调用相应的函数即可。在有历史记录和备份还原状态的类中可以使用该设计模式。
备忘录模式的实现感觉违背了开放-封闭原则,扩展性也不是很好,比如:我要新增一个状态信息:魔力值,我要在游戏角色中添加一个魔力值属性,在构造函数中新增魔力值属性的初始化,修改备份游戏属性的函数,当然要事先在备忘录类中的添加魔力值属性,修改备忘录类的构造函数,…。从这里可以看到,新增一个属性,几乎所有的方法都要修改,这真的很不友好。
个人觉得把游戏中的所有属性从角色中分离出来封装成一个新的类-游戏状态类,游戏角色类以组合关系包含一个游戏状态类,对游戏状态的更新由这个新的类来事先,游戏角色类只要调用相应函数即可;备忘录类也只要备份相应的游戏状态类的对象即可,如果以后需要新增或者修改,只要对游戏状态类更新即可。当然可能也会修改游戏角色类和备忘录类,但是个人认为修改的机会少一些。
或者在游戏状态类的基础上,直接在游戏角色类中定义状态类的两个对象,一个表示当前状态信息,一个表示备份状态信息,这样是不是更简单些呢?
欢迎大家留言,给出你的想法,谢谢大家!
参考
《大话设计模式》