博主看了许多文章和一些书,发现要么代码不全,要么对备忘录的理解有偏差,要么干脆根本就不是备忘录模式,经过博主查阅十余篇文章和详细研究书本备忘录模式,总结出这篇精华的c++备忘录模式文章,感兴趣的朋友可以阅读和提出建议。
别名Token。
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
a1 定义一个备忘录类Memento,定义两个接口函数getState()和setState();
a2 定义一个原发器类Originator,定义两个接口函数createMemento()和setMemento();前一个函数被管理者类的存储函数调用Caretaker::save(),后一个函数被管理者类的恢复函数调用Caretaker::undo();
a3 定义一个管理者类Caretaker(),定义两个接口函数save()和undo();前一个函数用于存储对象当前状态,后一个函数用于对象恢复某一时刻状态;
本文为了简化代码,凸显出状态模式代码思想和思路,用std::sting state为对象,保存对象state当前状态和恢复对象state最开始状态,具体可以查看下面代码实现。
具体的实现由两个版本,一个将Originator声明为Memnto的友元类,另一个是Memnto直接提供公共接口以供窄接口调用。
MementoPattern.cpp
#include
#include
#include
using namespace std;
#define DELETE(pointer) delete (pointer); (pointer)=nullptr
class Originator;
class Memento // 备忘录类
{
public:
~Memento(){}
// 提供窄接口,以供管理者类Caretaker调用
private: // 所有接口和变量声明为私有,目的是为了只提供给产生这个备忘录的原发器Originator调用,其它接口无法直接调用
friend Originator; // 目的是为了访问Memnto的private和protected成员函数和成员变量
string state;
Memento(string state) :state(state) {}
const string getState() const { return state; }
void setState(string state) { this->state = state; }
};
class Originator // 原发器类
{
string state;
public:
Originator(string state) :state(state){}
Memento* createMemento() { return new Memento(state); } // 返回对象state当前状态
void setMemento(Memento *memento) { state = memento->getState(); } // 设置对象state返回某一时刻状态
void changeState(string state) { this->state = state; } // 对象state的状态发生改变后需要保存
const void showState()const { cout << "state==" << state << endl; }
};
class Caretaker // 管理者类
{
vector<Memento*> mementos; // 不需要在参数列表初始化
Originator *originator;
public:
Caretaker(Originator *originator) : originator(originator){}
~Caretaker() { // 析构时手动删除vector容器指针指向的内存
for (auto it = mementos.begin(); it != mementos.end(); ++it) {
if ((*it) != nullptr) {
DELETE (*it);
}
}
}
void save(Memento *memento) { mementos.push_back(memento); } // 记录备忘录某一时刻的状态
void undo(int index) { originator->setMemento(mementos.at(index)); } // 返回备忘录某个时刻index的状态
};
void doMementoPattern()
{
string state{ "初始状态" };
Originator *originator = new Originator(state);
Caretaker *caretaker = new Caretaker(originator);
caretaker->save(originator->createMemento()); // 保存初始状态
originator->showState(); // 打印初始状态
originator->changeState(string{ "状态1" }); // 状态发生改变1
caretaker->save(originator->createMemento());
originator->showState();
originator->changeState(string{ "状态2" }); // 状态发生改变2
caretaker->save(originator->createMemento());
originator->showState();
caretaker->undo(0); // 返回到最初状态
originator->showState();
DELETE(caretaker);
DELETE(originator);
}
main.cpp
#include
extern void doMementoPattern();
int main()
{
doMementoPattern();
system("pause");
return 1;
}
MementoPattern.cpp
#include
#include
#include
using namespace std;
#define DELETE(pointer) delete (pointer); (pointer)=nullptr
class Memento // 备忘录类
{
string state;
public:
Memento(string state) :state(state) {}
const string getState() const { return state; }
void setState(string state) { this->state = state; }
};
class Originator // 原发器类
{
string state;
public:
Originator(string state) :state(state){}
Memento* createMemento() { return new Memento(state); } // 返回对象state当前状态
void setMemento(Memento *memento) { state = memento->getState(); } // 设置对象state返回某一时刻状态
void changeState(string state) { this->state = state; } // 对象state的状态发生改变后需要保存
const void showState()const { cout << "state==" << state << endl; }
};
class Caretaker // 管理者类
{
vector<Memento*> mementos; // 不需要在参数列表初始化
Originator *originator;
public:
Caretaker(Originator *originator) : originator(originator){}
~Caretaker() { // 析构时手动删除vector容器指针指向的内存
for (auto it = mementos.begin(); it != mementos.end(); ++it) {
if ((*it) != nullptr) {
DELETE (*it);
}
}
}
void save(Memento *memento) { mementos.push_back(memento); } // 记录备忘录某一时刻的状态
void undo(int index) { originator->setMemento(mementos.at(index)); } // 返回备忘录某个时刻index的状态
};
void doMementoPattern()
{
string state{ "初始状态" };
Originator *originator = new Originator(state);
Caretaker *caretaker = new Caretaker(originator);
caretaker->save(originator->createMemento()); // 保存初始状态
originator->showState(); // 打印初始状态
originator->changeState(string{ "状态1" }); // 状态发生改变1
caretaker->save(originator->createMemento());
originator->showState();
originator->changeState(string{ "状态2" }); // 状态发生改变2
caretaker->save(originator->createMemento());
originator->showState();
caretaker->undo(0); // 返回到最初状态
originator->showState();
DELETE(caretaker);
DELETE(originator);
}
mian.cpp
#include
extern void doMementoPattern();
int main()
{
doMementoPattern();
system("pause");
return 1;
}
备忘录模式核心在于保存一个对象某个时刻部分或者全部状态,以便客户返回时可以取消撤回那个时刻的状态。也就是说,核心思想是保存一个对象状态,当状态改变后用保存的对象赋值给当前对象即可。其实现跟原型模式不同,原型模式主要是对整个对象的克隆,无法做到部分克隆以及接口对所有客户开放,破坏开闭原则。
C++ 备忘录模式 - 开启月光宝盒
设计模式——备忘录模式(C++实现)
设计模式C++实现(2)——备忘录模式
陈建忠设计模式(参考:哔哩哔哩C++设计模式!!!)
Erich Gamma,Richard Helm.《设计模式 可复用面向对象软件的基础》[M].机械工业出版社,2019: