备忘录模式简介
使用Git的时候,代码有问题了,可以checkout到上一个版本,备忘录模式就是这种机制,用户可以方便的制定恢复到指定的某个历史状态。
Ctrl + Z 就是一种备忘录模式。
备忘录模式:在不破坏封装的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
备忘录模式结构
备忘录模式主要有以下角色:
- Originator(原发器):通过创建一个备忘录类存储当前的内部状态,也可以使用备忘录来恢复其内部状态,通常是将系统中需要保存内部状态的类设计为原发器;
- Memento(备忘录):用于存储原发器的内部状态。备忘录的设计可以参考原发器的设计,根据需要确定备忘录类中的属性;除了原发器类对象,不允许其他对象修改备忘录。
- Caretaker(负责人):负责保存备忘录,可以存储一个或多个备忘录对象,但是负责人只负责保存对象,不能修改对象,也不必知道对象的实现细节。
备忘录模式代码实例
#include <iostream>
using namespace std;
class RoleStateMemento
{
public:
RoleStateMemento(unsigned iBlood, unsigned iAttack, unsigned iDefense) : m_iBlood(iBlood), m_iAttack(iAttack), m_iDefense(iDefense){}
private:
friend class GameRole;
unsigned GetBloodValue() { return m_iBlood; }
unsigned GetAttackValue() { return m_iAttack; }
unsigned GetDefenseValue() { return m_iDefense; }
unsigned m_iBlood; // 生命力
unsigned m_iAttack; // 攻击力
unsigned m_iDefense; // 防御力
};
class GameRole
{
public:
GameRole() : m_iBlood(100), m_iAttack(100), m_iDefense(100){}
// 存档
RoleStateMemento *SaveState() { return new RoleStateMemento(m_iBlood, m_iAttack, m_iDefense); }
// 恢复存档
void RecoveryState(RoleStateMemento *pRoleState)
{
m_iBlood = pRoleState->GetBloodValue();
m_iAttack = pRoleState->GetAttackValue();
m_iDefense = pRoleState->GetDefenseValue();
cout<<"Recovery..."<<endl;
}
void ShowState()
{
cout<<"Blood:"<<m_iBlood<<endl;
cout<<"Attack:"<<m_iAttack<<endl;
cout<<"Defense:"<<m_iDefense<<endl;
}
void Fight()
{
m_iBlood -= 100;
m_iAttack -= 10;
m_iDefense -= 20;
if (m_iBlood == 0)
{
cout<<"Game Over"<<endl;
}
}
private:
unsigned m_iBlood; // 生命力
unsigned m_iAttack; // 攻击力
unsigned m_iDefense; // 防御力
};
class RoleStateCaretaker
{
public:
void SetRoleStateMemento(RoleStateMemento *pRoleStateMemento) { m_pRoleStateMemento = pRoleStateMemento; }
RoleStateMemento *GetRoleStateMemento() { return m_pRoleStateMemento; }
private:
RoleStateMemento *m_pRoleStateMemento;
};
int main()
{
GameRole *pLiXY = new GameRole(); // 创建李逍遥这个角色
pLiXY->ShowState(); // 显示初始的状态
// 存档
RoleStateCaretaker *pRoleStateCaretaker = new RoleStateCaretaker();
pRoleStateCaretaker->SetRoleStateMemento(pLiXY->SaveState());
// 开始打大BOSS
pLiXY->Fight();
pLiXY->ShowState();
// 读档,从新开始
pLiXY->RecoveryState(pRoleStateCaretaker->GetRoleStateMemento());
pLiXY->ShowState();
return 0;
}
备忘录模式总结
优点:
- 实现状态恢复、撤销操作的功能,用户可以恢复到指定的历史状态,让软件系统更加人性化;
- 备忘录封装了信息,除了原生器以外,其他对象访问不了备忘录的代码;
缺点:
- 资源消耗大。如果需要保存原生器对象的多个历史状态,那么将创建多个备忘录对象;或者如果原生器对象的很多状态都需要保存,也将消耗大量存储资源。
适用环境:
- 保存一个对象的历史状态,系统需要设计回退或者撤销功能;
- 备忘录类可以封装一个对象的历史状态,避免对象的历史状态被外界修改。