备忘录模式
备忘录模式(Memento Pattern)在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
备忘录模式通用类图
Originator 发起人角色
记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据。
Memento 备忘录角色
负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态。
Caretaker 备忘录管理员角色
对备忘录进行管理,保存和提供备忘录。
优点:
保持封装边界 使用备忘录可以避免暴露一些只应由原发器管理却又必须存储在原发器之外的信息。该模式把可能很复杂的Originator内部信息对其他对象屏蔽起来,从而保持了封装边界。
简化了Originator
缺点:
使用备忘录可能代价很高如果原发器在生成备忘录时必须拷贝并存储大量的信息,或者客户非常频繁地创建备忘录和恢复原发器状态,可能会导致非常大的开销。除非封装和恢复Originator状态的开销不大,否则该模式可能并不合适。
定义窄接口和宽接口 在一些语言中可能难以保证只有原发器可访问备忘录的状态。
维护备忘录的潜在代价 管理器负责删除它所维护的备忘录。然而,管理器不知道备忘录中有多少个状态。因此当存储备忘录时,一个本来很小的管理器,可能会产生大量的存储开销。
C++通用源码
#include <iostream> #include <string> using namespace std; class Memento{ private: string state; Memento(string _state):state(_state){}; string getState(){return state;} void setState(string state){this->state=state;} friend class Originator; public: ~Memento(){}; }; class Originator{ private: string state; public: string getState(){ return state; } void setState(string state){ this->state = state; } Memento * CreateMemento(){ return new Memento(this->state); } void restoreMemento(Memento * _memento){ this->setState(_memento->getState()); } }; class CareTaker{ private: Memento * memento; public: CareTaker():memento(NULL){}; Memento * getMemento(){ return memento; }; void setMemento(Memento *memento){ if(this->memento!=NULL) //若之前有备份,则先删除之前的备份 delete this->memento; this->memento = memento; } ~CareTaker(){ if(this->memento!=NULL) delete memento; } }; int main() //可以看到,main函数里没有直接使用Memento类的对象 { Originator originator; //定义发起人 CareTaker caretaker; //定义管理角色 originator.setState("Hello World!"); cout<<originator.getState()<<endl; caretaker.setMemento(originator.CreateMemento()); //创建备份 originator.setState("I will be back!"); cout<<originator.getState()<<endl; originator.restoreMemento(caretaker.getMemento()); //恢复备份 cout<<originator.getState()<<endl; return 0; }
运行结果
昨夜星辰昨夜风,画楼西畔桂堂东。
身无彩凤双飞翼,心有灵犀一点通。
隔座送钩春酒暖,分曹射覆蜡灯红。
嗟余听鼓应官去,走马兰台类转蓬。