所谓备忘录模式,就是由一个专门的备忘录类来对主体的状态进行保存。当主体处于某个状态时,主体可以生成一个备忘录类对象,主体的状态就保存在该对象中。然后将该备忘录对象保存在备忘录的管理类中;当主体状态改变后,若要恢复某个指定状态,调用备忘录的管理类来获取指定的备忘录类对象,然后根据该备忘录类对象来恢复状态。
例如,游戏当中,存档就是一个备忘录类对象。当玩家需要保存进度时,根据当前进度生成一个存档,然后将该存档保存在存档管理器中。当玩家需要读取某个进度时,从存档管理器中提取一个存档,然后将该存档进行载入即可。
备忘录模式供涉及3个类:
① 主体类:可以生成备忘录,或根据备忘录恢复状态
② 备忘录类:含属性与接口,负责主体状态的保存
③ 备忘录管理类:用于保存(而不是生成)传入的备忘录,以及返回保存的备忘录
1. 备忘录类
备忘录类负责保存主体的状态。
由于备忘录是属于主体的,所以这里可以将备忘录的所有接口及成员变量都封装为private,然后对主体类friendclassOriginator。这样,主体类可以直接访问备忘录的成员变量及成员函数。
//备忘录类
class Memento
{
private:
//将Originator为friend类,可以访问内部信息,但是其他类不能访问
friend class Originator;
Memento(const string& state) { this->_state = state; };
void SetState(const string& state) { this->_state = state; };
string GetState();
private:
string _state;
};
2. 备忘录管理类
备忘录管理类负责备忘录的保存和获取工作。
一般来说,备忘录管理类不应具有读取或者修改备忘录对象的能力。这也是1中备忘录的所有接口都声明为private的原因。
//备忘录管理类
class Caretaker
{
public:
void SetMemento(Memento* pMemento) { this->_memento = pMemento; }
Memento* GetMemento() { return this->_memento; }
private:
Memento* _memento;
};
3. 主体类
主体类可以创建一个备忘录;同时也可以传入一个备忘录以更改自身状态。
注意主体类是跟备忘录直接交互的,而非备忘录管理类。
//主体类
class Originator
{
public:
Originator(const string& state) { this->_state = state; }
void RestoreToMemento(Memento* pMemento) { this->_state = pMemento->GetState(); }
Memento* CreateMemento() { return new Memento(this->_state); }
void SetState(const string& state) { this->_state = state; }
string GetState() { return this->_state; }
private:
string _state;
};
4. 用户使用
用户使用时,由主体产生一个备忘录,然后将备忘录保存在备忘录管理类中。
当需要恢复状态时,从备忘录管理类获取状态,然后主体根据传入的备忘录来进行状态的恢复。
void main()
{
//初始化对象,状态为“StateA”
Originator* originator = new Originator("StateA");
//将备忘录保存在备忘录管理类中
Caretaker* pTaker = new Caretaker();
pTaker->SetMemento(originator->CreateMemento());
//改变状态
originator->SetState("StateB");
//恢复状态
originator->RestoreToMemento(pTaker->GetMemento());
}
备忘录模式可以在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态。
结合命令模式,可以实现操作的撤销/重做等功能。