1、简介
备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。
备忘录模式将创建状态快照 (Snapshot) 的工作委派给实际状态的拥有者原发器 (Originator) 对象。 这样其他对象就不再需要从 “外部” 复制编辑器状态了, 编辑器类拥有其状态的完全访问权, 因此可以自行生成快照。
模式建议将对象状态的副本存储在一个名为备忘录 (Memento) 的特殊对象中。 除了创建备忘录的对象外, 任何对象都不能访问备忘录的内容。 其他对象必须使用受限接口与备忘录进行交互, 它们可以获取快照的元数据 (创建时间和操作名称等), 但不能获取快照中原始对象的状态。
2、结构
备忘录模式的核心是设计备忘录类以及用于管理备忘录的管理者类,备忘录模式的主要角色如下:
- 发起人(Originator)角色: 记录当前对象的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
- 备忘录(Memetor)角色: 负责存储发起人对象的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者(Caretaker)角色: 对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
3、C++实现
#include <iostream>
#include <string>
using namespace std;
//备忘录角色
class Memento {
private:
friend class Originator;
Memento(const string& st) {
_st = st;
}
void SetState(const string& st) {
_st = st;
}
string GetState() {
return _st;
}
private:
string _st;
};
//发起人角色
class Originator {
public:
Originator() {
_mt = nullptr;
}
Originator(const string &st) {
_st = st;
_mt = nullptr;
}
Memento* CreateMemento() {
return new Memento(_st);
}
void SetMemento(Memento* mt) {
_mt = mt;
}
void RestoreToMemento(Memento* mt) {
_st = mt->GetState();
}
string GetState() {
return _st;
}
void SetState(const string& st) {
_st = st;
}
void PrintState() {
cout << _st << "..." << endl;
}
private:
string _st;
Memento *_mt;
};
int main() {
Originator *o = new Originator();
o->SetState("old");
o->PrintState();
//创建历史记录
Memento *m = o->CreateMemento();
o->SetState("new");
o->PrintState();
//回复历史记录
o->RestoreToMemento(m);
o->PrintState();
delete o;
delete m;
return 0;
}
执行结果
4、备忘录模式优缺点
优点:
- 可以随时保存一个对象的状态,并在需要时恢复到该状态,提高了程序的灵活性和可维护性。
- 发起人和备忘录之间的封装使得客户端无法直接访问备忘录,从而更好地保护了对象的状态信息。
- 管理者可以管理多个备忘录,提供了更好的历史记录和回滚功能。
缺点:
- 如果客户端过于频繁地创建备忘录, 程序将消耗大量内存。
- 负责人必须完整跟踪原发器的生命周期, 这样才能销毁弃用的备忘录。
- 绝大部分动态编程语言 (例如 PHP、 Python 和 JavaScript) 不能确保备忘录中的状态不被修改。
5、使用场景
-
需要保存和恢复数据的相关状态场景。如玩游戏时的中间结果的存档功能。
-
提供一个可回滚(rollback)的操作。如 Word、记事本、等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。