备忘录模式通过发起人、备忘录和管理者三者协作,在不破坏封装性的前提下实现状态保存与恢复;发起人创建并恢复状态,备忘录由发起人私有嵌套定义以保护内部数据,管理者仅负责存储和传递备忘录指针,无法访问其内容,从而确保安全性与封装性。

在C++中实现备忘录模式,核心目标是在不破坏封装性的前提下捕获并恢复一个对象的内部状态。这个模式常用于实现撤销(undo)功能、状态快照或事务回滚等场景。关键是将状态保存与恢复逻辑分离,避免暴露对象的私有成员。
备忘录模式的基本角色
备忘录模式包含三个主要角色:
- 发起人(Originator):拥有内部状态的对象,能创建备忘录来保存当前状态,也能通过备忘录恢复状态。
- 备忘录(Memento):负责存储发起人的内部状态。通常设计为发起人的嵌套类或友元类,以访问其私有成员,但对外部只提供有限接口。
- 管理者(Caretaker):负责保存和管理备忘录对象,但不能访问或修改备忘录中的状态数据。
使用嵌套类和友元实现封装
为了不破坏封装性,可以将备忘录类定义为发起人的私有嵌套类,并允许管理者通过指针或引用间接持有它。这样外部无法直接构造或访问状态字段。
#include <iostream>
#include <string>
#include <stack>
<p>class Originator {
private:
std::string state;</p><pre class='brush:php;toolbar:false;'>// 私有嵌套类作为备忘录
class Memento {
friend class Originator; // 允许Originator访问私有成员
private:
std::string savedState;
Memento(const std::string& s) : savedState(s) {}
public:
const std::string& getState() const { return savedState; }
};public: void setState(const std::string& s) { state = s; std::cout << "State set to: " << s << "\n"; }
std::string getState() const {
return state;
}
// 创建备忘录
Memento* saveToMemento() const {
return new Memento(state);
}
// 从备忘录恢复状态
void restoreFromMemento(Memento* m) {
if (m) {
state = m->getState();
std::cout << "State restored to: " << state << "\n";
}
}};
立即学习“C++免费学习笔记(深入)”;
// 管理者:保存和管理多个备忘录(如用于撤销栈) class Caretaker { private: std::stack<Originator::Memento*> history;
public: void push(Originator::Memento* m) { history.push(m); }
Originator::Memento* pop() {
if (history.empty()) return nullptr;
Originator::Memento* m = history.top();
history.pop();
return m;
}
~Caretaker() {
while (!history.empty()) {
delete history.top();
history.pop();
}
}};
立即学习“C++免费学习笔记(深入)”;
实际使用示例
下面演示如何用该模式实现简单的撤销操作:
int main() {
Originator originator;
Caretaker caretaker;
<pre class='brush:php;toolbar:false;'>originator.setState("State1");
caretaker.push(originator.saveToMemento());
originator.setState("State2");
caretaker.push(originator.saveToMemento());
originator.setState("State3");
// 撤销一次
Originator::Memento* m = caretaker.pop();
originator.restoreFromMemento(m);
delete m; // 可选:由Caretaker统一管理时可省略
// 再撤销一次
m = caretaker.pop();
originator.restoreFromMemento(m);
return 0;}
关键设计要点
要真正保证封装性和安全性,需注意以下几点:
- 备忘录类应为发起人的私有类,防止外部构造或篡改。
- 管理者只能持有和传递备忘录指针,不能访问其内容。
- 使用智能指针(如std::unique_ptr)可更好管理生命周期,避免内存泄漏。
- 若状态较大,考虑深拷贝或共享数据(如使用copy-on-write)优化性能。
基本上就这些。这种实现方式既保护了对象的私有状态,又实现了灵活的状态保存与恢复机制。










