1、备忘录模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
2、涉及角色:
1)发起人(Originator):负责创建一个备忘录(Memento),用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。发起人可以根据需要决定备忘录存储自己的哪些内部状态。
2)备忘录(Memento):负责存储Originator对象的内部状态,并可以防止Orginator以外的其他对象访问备忘录,备忘录有两个接口:管理者(Caretaker)只能看备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可以看到备忘录的宽接口,允许他访问返回到先前状态所需要的所有数据。
3)管理者(caretaker): 负责管理备忘录Memento,不能对Memento的内容访问或者操作。
3、举个简单的例子,我们玩游戏的时候都会保存进度,所保存的进度以文件的形式存在,这样下次就可以继续玩,而不用从头开始。这里的进度其实就是游戏的内部状态,而这里的文件相当于是在游戏之外保存状态,这样,下次就可以从文件中读入保存的进度,从而恢复到原来的状态。
#include<iostream>
#include<vector>
using namespace std;
class Memento
{
public:
int m_vitality; //生命值
int m_attack; //进攻值
int m_defense; //防御值
public:
Memento(int vitaity,int attack,int defense):
m_vitality(vitaity),m_attack(attack),m_defense(defense){}
Memento& operator = (const Memento &memento) //对=运算符重载
{
m_vitality = memento.m_vitality;
m_attack = memento.m_attack;
m_defense = memento.m_defense;
return *this;
}
};
//游戏角色(发起者)
class GameRole
{
private:
int m_vitality;
int m_attack;
int m_defense;
public:
GameRole():m_vitality(100),m_attack(100),m_defense(100){}
Memento Save() //保存进度,只与Memento对象交互,不涉及到caretaker
{
Memento memento(m_vitality,m_attack,m_defense);
return memento;
}
void Load(Memento memento) //载入进度,只与Memento对象交互,不涉及到caretaker
{
m_vitality = memento.m_vitality;
m_attack = memento.m_attack;
m_defense = memento.m_defense;
}
void show()
{
cout<<"vitality:"<<m_vitality<<",attack:"<<m_attack<<",defense:"<<m_defense<<"。"<<endl;
}
void Attack()
{
m_vitality = m_vitality - 10;
m_attack = m_attack - 10;
m_defense = m_defense - 10;
}
};
//备忘录的管理者,保存进度的地方
class Caretaker
{
private:
vector<Memento> m_vecMemento;
public:
Caretaker(){}
void Save(Memento memento)
{
m_vecMemento.push_back(memento);
}
Memento Load(int state)
{
return m_vecMemento[state];
}
};
int main()
{
Caretaker caretaker;
GameRole role;
GameRole role1;
role.show();
caretaker.Save(role.Save());//保存最开始的进度
role.Attack(); //受到攻击以后
role.show();
role1 = role; //玩家1想接着刚才进度玩
role1.show();
role.Load(caretaker.Load(0)); //回到刚开始的进度玩
role.show();
return 0;
}
游戏发起者保存进度在备忘录里,在自己的类里面save返回一个Memento对象,然后Caretaker对象里面保存Memento的对象,将其添加到容器内,游戏发起者想要还原到原来的状态,Caretaker对象从容器内取出备忘录对象返回给游戏发起者,游戏发起者加载。
4、备忘录模式的优点
1)有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取,这时,使用备忘录模式可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。
2)本模式简化了发起人类。发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需要的这些状态的版本。
3)当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
5、备忘录模式的缺点:
1)如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
2)当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。
其中部分内容参考于:https://blog.csdn.net/wuzhekai1985/article/details/6672906