1、描述
备忘录是一种行为设计模式,允许生成对象状态的快照并在以后将其还原。
备忘录不会影响它所处理的对象的内部结构,也不会影响快照中保存的数据。
2、结构图
- 原发器(Originator)可以生成自身状态的快照,也可以在需要时通过快照恢复自身状态。
- 备忘录(Memento)是原发器状态快照的值对象。通常做法是将备忘录设为不可变的,并通过构造函数一次性传递数据。
- 负责人(Caretaker)对备忘录进行管理、保存和提供备忘录。
3、C++代码
#include <string>
#include <iostream>
#include <vector>
#include <time.h>
//备忘录接口提供了一种获取元数据的方法,例如创建日期或名称。但是,它不会暴露原发器的状态
class Memento {
public:
virtual std::string GetName() const = 0;
virtual std::string date() const = 0;
virtual std::string state() const = 0;
};
//具体的备忘录类包含了存储原发器状态的基础设施
class ConcreteMemento : public Memento {
private:
std::string state_;
std::string date_;
public:
ConcreteMemento(std::string state) : state_(state) {
this->state_ = state;
time_t now = time(0);
this->date_ = ctime(&now);
}
//原发器使用这个方法恢复它的状态
std::string state() const override {
return this->state_;
}
//其他的方法由负责人使用来展示元数据
std::string GetName() const override {
return this->date_ + " / (" + this->state_.substr(0, 9) + "...)";
}
std::string date() const override {
return this->date_;
}
};
//原发器包含一些可能会随着时间改变的重要的状态。它也定义了一个方法用来将状态保存到备忘录和
//另一个方法用来从备忘录中恢复状态
class Originator {
private:
std::string state_;
std::string GenerateRandomString(int length = 10) {
const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(alphanum) - 1;
std::string random_string;
for (int i = 0; i < length; i++) {
random_string += alphanum[std::rand() % stringLength];
}
return random_string;
}
public:
Originator(std::string state) : state_(state) {
std::cout << "Originator: My initial state is: " << this->state_ << "\n";
}
//原发器的业务逻辑可能会改变其内部状态。因此,客户需要在调用该方法前备份状态。
void DoSomething() {
std::cout << "Originator: I'm doing something important.\n";
this->state_ = this->GenerateRandomString(30);
std::cout << "Originator: and my state has changed to: " << this->state_ << "\n";
}
//将当前状态备份到备忘录中
Memento *Save() {
return new ConcreteMemento(this->state_);
}
//从备忘录中恢复状态
void Restore(Memento *memento) {
this->state_ = memento->state();
std::cout << "Originator: My state has changed to: " << this->state_ << "\n";
}
};
//负责人并不依赖具体的备忘录类。因此,它并不需要获取保存在备忘录中的原发器状态。
//它只通过备忘录基类接口操作所有的备忘录
class Caretaker {
private:
std::vector<Memento *> mementos_;
Originator *originator_;
public:
Caretaker(Originator *originator) : originator_(originator) {
this->originator_ = originator;
}
void Backup() {
std::cout << "\nCaretaker: Saving Originator's state...\n";
this->mementos_.push_back(this->originator_->Save());
}
void Undo() {
if (!this->mementos_.size()) {
return;
}
Memento *memento = this->mementos_.back();
this->mementos_.pop_back();
std::cout << "Caretaker: Restoring state to: " << memento->GetName() << "\n";
try {
this->originator_->Restore(memento);
} catch (...) {
this->Undo();
}
}
void ShowHistory() const {
std::cout << "Caretaker: Here's the list of mementos:\n";
for (Memento *memento : this->mementos_) {
std::cout << memento->GetName() << "\n";
}
}
};
//客户端代码
void ClientCode() {
Originator *originator = new Originator("Super-duper-super-puper-super.");
Caretaker *caretaker = new Caretaker(originator);
caretaker->Backup();
originator->DoSomething();
caretaker->Backup();
originator->DoSomething();
caretaker->Backup();
originator->DoSomething();
std::cout << "\n";
caretaker->ShowHistory();
std::cout << "\nClient: Now, let's rollback!\n\n";
caretaker->Undo();
std::cout << "\nClient: Once more!\n\n";
caretaker->Undo();
delete originator;
delete caretaker;
}
int main() {
std::srand(static_cast<unsigned int>(time(NULL)));
ClientCode();
return 0;
}
参考