备忘录模式(Memento Pattern)
备忘录模式(Memento Pattern)
定义
- 备忘录模式是一种 行为型设计模式,允许在不破坏对象封装性的前提下,捕获并保存对象的内部状态,并在需要时恢复该状态。它通过将对象状态封装在独立的“备忘录对象”中,实现状态的保存与恢复逻辑的解耦。
核心思想
-
状态快照:将对象状态保存为一个不可变的快照(备忘录对象)。
-
封装性保护:不直接暴露对象内部状态,而是通过备忘录类间接操作。
-
职责分离:由独立的“备忘录”类存储状态,由“负责人”类管理状态历史,降低对象与状态管理的耦合。
模式结构
备忘录模式包含三个核心角色:
| 角色 | 职责 |
|---|---|
| Originator | 需要保存状态的对象(如文本编辑器、游戏角色),负责创建和恢复备忘录对象}。 |
| Memento | 存储 Originator 内部状态的不可变快照,仅允许 Originator 访问其数据}。 |
| Caretaker | 管理备忘录历史记录(如栈结构实现撤销/重做),不直接操作备忘录内容}。 |
主要解决的问题
-
撤销/重做功能:如文本编辑器的撤销操作、游戏的存档读档。
-
状态回滚:在事务处理中恢复到之前的正确状态。
-
封装性保护:避免直接暴露对象内部状态,防止外部代码破坏其一致性。
代码示例
- 以下是一个文本编辑器撤销功能的 C# 实现:
using System;
// 备忘录(Memento)
public class TextMemento
{
public string Content { get; } // 不可变快照
public TextMemento(string content)
{
Content = content;
}
}
// 发起人(Originator)
public class TextEditor
{
private string _content;
public string Content
{
get => _content;
set
{
Console.WriteLine($"修改内容为:{value}");
_content = value;
}
}
// 创建备忘录
public TextMemento Save()
{
Console.WriteLine("保存当前内容到备忘录");
return new TextMemento(_content);
}
// 恢复备忘录
public void Undo(TextMemento memento)
{
if (memento != null)
{
_content = memento.Content;
Console.WriteLine($"撤销到内容:{_content}");
}
}
}
// 负责人(Caretaker)
public class History
{
private Stack<TextMemento> _history = new Stack<TextMemento>();
public void Push(TextMemento memento) => _history.Push(memento);
public TextMemento? Pop() => _history.Count >0 ? _history.Pop() : null;
}
// 客户端代码
class Program
{
static void Main()
{
var editor = new TextEditor();
var history = new History();
editor.Content = "第一版内容";
history.Push(editor.Save()); // 保存状态1
editor.Content = "第二版内容";
history.Push(editor.Save()); // 保存状态2
editor.Content = "第三版内容"; // 未保存
// 执行两次撤销
editor.Undo(history.Pop()); // 输出:撤销到内容:第二版内容
editor.Undo(history.Pop()); // 输出:撤销到内容:第一版内容
}
}
输出结果:
修改内容为:第一版内容
保存当前内容到备忘录
修改内容为:第二版内容
保存当前内容到备忘录
修改内容为:第三版内容
撤销到内容:第二版内容
撤销到内容:第一版内容
总结
优点:
-
严格保护对象封装性,状态保存逻辑与业务逻辑分离。
-
简化 Originator 类,状态管理由 Caretaker 处理。
缺点:
- 频繁保存大对象可能导致内存消耗增加。
适用场景:
-
需要实现撤销/重做功能(如编辑器、绘图软件)。
-
需要生成对象状态快照(如游戏存档、事务回滚)。

浙公网安备 33010602011771号