意图:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态
适用性:
1必须保存一个对象在某一个时刻的部分状态,这样以后需要时才能恢复到先前的状态
2如果用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
效果:
1保持封装边界 使用备忘录可以避免暴露一些只应由原发器管理却又必须储存在原发器之外的信息。
2简化了原发器 让客户管理它们请求的状态会简化Originator,并且使得客户工作结束时无需通知原发器
3使用 Memento可能代价很高 如果原发器在生成备忘录时必须拷贝并储存大量的信息,或者客户非常频繁地创建备忘录,可能会导致非常大的开销
4定义宽接口和窄接口
实现:
1语言支持 Memento有两个接口,一个为原发器所使用的宽接口,一个为其它对象所使用的窄接口。在C++中,可将Originator作为Memento的一个友元,并使接口为私有。只有窄接口被声明为公共的。
2存储式增量改变
如果备忘录的创建及返回的顺序是可测的,备忘录可以仅存储原发器内部状态的增量改变
The code is below.
Memento.h
- #include <string>
- #include <iostream>
- using namespace std;
- #define MAX_NUM 30
- class Point
- {
- public:
- Point(int x, int y):_x(x),_y(y)
- {
- cout<<"Create a point, x is" <<_x<<", y is"<<_y<<endl;
- }
- private:
- int _x,_y;
- };
- class ConstraintSolverMemento;
- class MoveCommand
- {
- public:
- MoveCommand()
- {cout<<"Create a move command"<<endl;
- for(int i=0;i<MAX_NUM;i++)
- _state[i]=0;
- }
- void Execute(string s);
- void Unexecute();
- private:
- ConstraintSolverMemento* _state[MAX_NUM];
- //Point _delta;
- };
- class ConstraintSolver
- {
- public:
- static ConstraintSolver* Instance();
- void solve() {cout<<"Solve it"<<endl;}
- void AddConstraint() {cout<<"Add constraint."<<endl;}
- void RemoveConstraint() {cout<<"Remove constraint."<<endl;}
- ConstraintSolverMemento* CreateMemento(string s);
- void SetMemento(ConstraintSolverMemento*);
- private:
- static ConstraintSolver* _instance;
- };
- class ConstraintSolverMemento
- {
- public:
- virtual ~ConstraintSolverMemento(){cout<<"Destory ConstraintSolverMemento"<<endl;}
- string getstate(){return state;}
- private:
- friend class ConstraintSolver;
- ConstraintSolverMemento(string s):state(s){}
- string state;
- };
Memento.cpp
- #include "Memento.h"
- #include <iostream>
- #include <string>
- using namespace std;
- ConstraintSolver* ConstraintSolver::_instance = 0;
- Constrai ConstraintSolverMemento(s);
- }
- void ConstraintntSolver* ConstraintSolver::Instance()
- {
- if (_instance == 0)
- _instance = new ConstraintSolver;
- return _instance;
- }
- ConstraintSolverMemento* ConstraintSolver::CreateMemento(string s)
- {
- cout<<"Create Memento"<<endl;
- return newSolver::SetMemento(ConstraintSolverMemento* s)
- {
- cout<<"Set Memento "<<s->getstate()<<endl;
- }
- void MoveCommand::Execute(string s)
- {
- ConstraintSolver* solver = ConstraintSolver::Instance();
- for (int i=0;i<MAX_NUM;i++)
- if ( _state[i] == 0)
- break;
- if(i<MAX_NUM)
- {
- _state[i] =solver->CreateMemento(s);
- cout<<"Execute " << i<<endl;
- }
- solver->solve();
- }
- void MoveCommand::Unexecute()
- {
- ConstraintSolver* solver = ConstraintSolver::Instance();
- for(int i=MAX_NUM-1;i>=0;i--)
- if(_state[i]!=0 )
- break;
- cout<<"unExecute " << i<<endl;
- if (i>=1)
- solver->SetMemento(_state[i-1]);
- else
- cout<<"Return back orginal state"<<endl;
- _state[i] = 0;
- solver->solve();
- }
main.cpp
- #include "Memento.h"
- #include <iostream>
- using namespace std;
- int main()
- {
- MoveCommand a;
- string s="down";
- a.Execute("down");
- a.Execute("up");
- a.Unexecute();
- a.Unexecute();
- return 0;
- }