设计模式十九:memento(备忘录)——对象行为型模式
memento(备忘录)——对象行为型模式
1.意图
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以将该对象恢复到之前保存的状态。
2.别名
Token
3.动机
有时候有必要记录一下对象的内部状态。但是对象通常又封装了部分或者所有的状态信息,使得其状态不能被其他对象访问,也就不可能在该对象之外保存状态。而暴露其内部状态又违反了封装原则。
我们可以用备忘录来解决这一问题。一个备忘录是一个对象,它存储另一个对象在某个瞬间的内部状态,而后者被称为备忘录的原发器。原发器用描述当前状态的信息初始化备忘录,只有原发器可以向备忘录中存取信息。
4.适用性
必须保存一个对象在某一个时刻的部分状态,这样以后需要时他才能恢复到先前的状态。
如果一个用接口来让其他对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的结构性。
5.结构
参考:http://www.cnblogs.com/jqbird/archive/2011/08/29/2158018.html
6.参与者
memento备忘录
备忘录存储原发器对象的内部状态。原发器根据需要决定备忘录存储原发器的那些内部状态。
防止原发器之外的其他对象访问备忘录。备忘录实际上有两个接口。管理者只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。相反,原发器能看到一个宽接口,允许它访问返回到先前状态所需的所有数据。理想情况是只允许生成本备忘录的那个原发器访问本备忘录的内部状态。
originator原发器
原发器创建一个备忘录,用来记录当前时刻他的内部状态
使用备忘录恢复内部状态
careTaker负责人
负责保存好备忘录
不能对备忘录的内容进行操作或者检查
7.协作
管理器向原发器请求一个备忘录,保留一段时间后,将其送回原发器
备忘录是被动的。只有创建备忘录的原发器会对他的状态进行赋值和检索
8.效果
1)保持封装边界
2)简化了原发器
3)使用备忘录可能代价很高
4)定义窄接口和宽接口
5)维护备忘录的潜在代价
9.实现
1)c++中,可以将originator作为memento的一个友元,并使memento宽接口为私有,只有窄接口应该被声明为公共的。
2)存储增量式改变
如果备忘录的创建机器返回的顺序是可以预测的,那么备忘录可以仅存储原发器内部状态的增量式改变。
10.代码示例
#include<iostream> using namespace std; class memento { public: memento(string state) { reserveState = state; cout<<"create a memento"<<endl; } string getState() { return reserveState; } void setState(string s) { reserveState = s; } private: string reserveState; }; class originator { public: originator(string str) { state = str; } memento *createMem() { return new memento(state); } string getState() { return state; } void setState(string s) { state = s; } void setMemento(memento *m) { state = m->getState(); } void show() { cout<<"the obj's state is"<<getState()<<endl; } private: string state; }; class careTaker { public: careTaker(memento *m) { men = m; } void setMem(memento *m) { men = m; } memento *getMem() { return men; } private: memento *men; }; int main() { cout<<"the original state"<<endl; originator *origi = new originator("the first state"); origi->show(); cout<<endl<<"reserve state"<<endl; memento *temp = origi->createMem(); careTaker *ct = new careTaker(temp); cout<<endl<<"change the state"<<endl; origi->setState("the second state"); origi->show(); cout<<endl<<"back to the original state"<<endl; origi->setMemento(ct->getMem()); origi->show(); }
代码写的不怎么样,只能意思一下这个模式
高端的可以参考
http://www.cnblogs.com/mayvar/archive/2011/09/08/wanghonghua_201109080336.html
11.相关模式
command
命令可使用备忘录来作为可撤销的操作维护状态
iterator
备忘录可用于迭代