备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下,捕获并外部化 一个对象的内部状态,以便以后可以恢复到这个状态。
核心概念
设计原则
备忘录模式遵循以下设计原则:
-
封装性原则:不暴露对象内部实现细节
-
单一职责原则:将状态保存与恢复职责分离
-
开闭原则:可以引入新的备忘录类型而不修改原始类
主要优点
-
状态保存:可以轻松实现撤销/恢复功能
-
封装保护:不破坏对象的封装性
-
简化原发器:将状态管理职责分离
-
时间快照:支持创建多个时间点的状态快照
模式结构
主要组件
-
Originator(原发器)
-
需要保存状态的对象
-
创建备忘录以保存当前状态
-
使用备忘录恢复状态
-
-
Memento(备忘录)
-
存储原发器的内部状态
-
防止原发器以外的对象访问
-
-
Caretaker(管理者)
-
负责保存备忘录
-
不操作或检查备忘录内容
-
完整代码示例
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// ==================== 备忘录类 ====================
class EditorMemento {
// 备忘录保存的状态
std::string content_;
// 只允许Editor类创建和访问备忘录
friend class Editor;
// 私有构造函数,确保只有Editor可以创建备忘录
explicit EditorMemento(const std::string& content)
: content_(content) {}
public:
// Editor可以通过此方法获取保存的状态
std::string getContent() const { return content_; }
};
// ==================== 原发器类 ====================
class Editor {
std::string content_;
public:
void type(const std::string& words) {
content_ += words;
}
std::string getContent() const {
return content_;
}
// 创建备忘录:保存当前状态
std::unique_ptr<EditorMemento> save() {
return std::make_unique<EditorMemento>(content_);
}
// 恢复状态:从备忘录恢复
void restore(const EditorMemento* memento) {
content_ = memento->getContent();
}
};
// ==================== 管理者类 ====================
class History {
std::vector<std::unique_ptr<EditorMemento>> mementos_;
Editor* editor_;
public:
explicit History(Editor* editor) : editor_(editor) {}
void backup() {
std::cout << "保存状态..." << std::endl;
mementos_.push_back(editor_->save());
}
void undo() {
if (mementos_.empty()) return;
auto memento = std::move(mementos_.back());
mementos_.pop_back();
std::cout << "恢复状态..." << std::endl;
editor_->restore(memento.get());
}
void showHistory() const {
std::cout << "\n历史记录:" << std::endl;
for (size_t i = 0; i < mementos_.size(); ++i) {
std::cout << i+1 << ". "
<< mementos_[i]->getContent().substr(0, 10)
<< (mementos_[i]->getContent().length() > 10 ? "..." : "")
<< std::endl;
}
}
};
// ==================== 客户端代码 ====================
int main() {
std::cout << "=== 文本编辑器撤销功能演示 ===" << std::endl;
Editor editor;
History history(&editor);
// 编辑并保存状态
editor.type("Hello, ");
history.backup();
editor.type("world! ");
history.backup();
editor.type("This is a memento pattern example.");
std::cout << "\n当前内容: " << editor.getContent() << std::endl;
// 显示历史
history.showHistory();
// 撤销一次
history.undo();
std::cout << "\n撤销后内容: " << editor.getContent() << std::endl;
// 再撤销一次
history.undo();
std::cout << "再撤销后内容: " << editor.getContent() << std::endl;
return 0;
}
模式变体
1. 增量备忘录
class IncrementalMemento {
std::string change_; // 只保存变化部分
friend class Editor;
explicit IncrementalMemento(const std::string& change) : change_(change) {}
};
class Editor {
std::string content_;
std::vector<std::unique_ptr<IncrementalMemento>> changes_;
public:
void type(const std::string& words) {
changes_.push_back(std::make_unique<IncrementalMemento>(words));
content_ += words;
}
void undo() {
if (changes_.empty()) return;
auto lastChange = changes_.back()->getChange();
content_.erase(content_.length() - lastChange.length());
changes_.pop_back();
}
};
2. 多状态备忘录
class FullStateMemento {
std::string content_;
int cursorPosition_;
std::vector<std::string> openFiles_;
// 可以保存更多状态...
friend class IDE;
FullStateMemento(const std::string& content, int pos, const std::vector<std::string>& files)
: content_(content), cursorPosition_(pos), openFiles_(files) {}
};
class IDE {
// 各种状态...
public:
std::unique_ptr<FullStateMemento> save() {
return std::make_unique<FullStateMemento>(content_, cursorPos_, openFiles_);
}
};
实际应用场景
-
文本编辑器:实现撤销/重做功能
-
游戏开发:保存游戏进度和存档
-
图形软件:绘图步骤的撤销
-
事务管理:操作回滚
-
配置管理:系统配置的保存和恢复