您的位置:首页 > 其它

设计模式笔记-Memento模式

2016-06-01 17:18 344 查看
备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。备忘的用例很多,比如word编辑,按ctrl+z撤消,如果没备忘,肯定是不能撤消回到之前状态的;打过游戏的人应该也了解,比如DOTA1,技术挺落后,不像DOTA2断线可以重连,比赛的时候为了防止游戏崩溃,时不时的裁判要手动保存游戏。



这里的Memento类保存的是Originator类的一个临时状态,它自己是不可以变化的--本来就是要保存原来状态,又被改变了那不是没意义了?所以这里我把Memento类的所有成员都设为private的,然后把Originator设为友元类,这样它就只能被Originator访问了。这个应该是个关注点,但看网上好多人没有这么弄,成员函数都是public的,可能很多人觉得只要我不去调用它不就行了嘛,违反了迪米特法则?“一个对象应该对其他对象保持最少的了解”,这就是设计的精妙。

还有一点就是:为了在Originator类中创建备忘,设计了备忘类Memento的一个带Originator*类型参数的拷贝构造函数!

//originator.h

#include<string>
#include "memento.h"

class Memento;
class Originator {
public:
Memento* createMemento();

void restoreMemento(Memento *);

void setState(string state)	{
_state = state;
}
string getState() {
return _state;
}
private:
std::string _state;
};
//originator.cpp

void Originator::restoreMemento(Memento *m) {
_state = m->getState();
}
Memento* Originator::createMemento() {
return new Memento(this);
}
//memento.h
#include"originator.h"
#include<string>

class Originator;
class Memento {
friend class Originator;
private:
Memento(Originator*);

void setState(std::string state) {
_state = state;
}
std::string getState() {
return _state;
}

private:
std::string _state;
};
//memento.cpp
#include "memento.h"
Memento::Memento(Originator *o) {
_state = o->getState();
}
完全可以不用Caretaker类,此时用户代码需要自己处理备份多状态逻辑(用容器)。 简单的实现如下:

class Caretaker {
void Save(Memento *lpMemento) {
m_vectMemento.push_back(lpMemento);
}

Memento* Load(int idx) {	//这里随便你怎么实现吧
return m_vectMemento[idx];
}

private:
vector<Memento*> m_vectMemento;
};
用户代码:

int main()
{
Originator originator;
originator.setState("old");
Memento * meme = originator.createMemento();
originator.setState("new");
originator.restoreMemento(meme);

//使用Caretaker类也可以
Originator originator;
Caretaker take;
originator.setState("old");
Memento * meme = originator.createMemento();
take.Save(meme);
originator.setState("new");
originator.restoreMemento(take.Load(0));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: