设计模式 18
- 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
- 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
- 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式
文章目录
- [设计模式 18](#设计模式 18)
-
- [备忘录模式(Memento Pattern)](#备忘录模式(Memento Pattern))
-
- [1 定义](#1 定义)
- [2 结构](#2 结构)
- [3 示例代码](#3 示例代码)
- [6 特点](#6 特点)
- [7 适用场景](#7 适用场景)
- [8 总结](#8 总结)
备忘录模式(Memento Pattern)
1 定义
备忘录模式的核心思想是将对象的状态保存在一个备忘录对象中,并允许在未来的某个时刻恢复该状态。备忘录模式保证了状态的封装性,外部对象无法直接访问备忘录中的内容,从而保护了原发器对象的内部细节。
2 结构
备忘录模式包含以下角色:
- 原发器(Originator): 创建备忘录以记录当前状态,并可以使用备忘录恢复先前状态。
- 备忘录(Memento): 存储原发器的内部状态,备忘录对外部是不可见的,只能由原发器访问。
- 负责人(Caretaker): 负责存储和管理备忘录,但不会修改或检查备忘录的内容。
UML 类图
scss
+---------------------------------------+
| Originator |
+---------------------------------------+
| - state: String |
| + CreateMemento(): Memento |
| + SetMemento(memento: Memento): void |
+---------------------------------------+
|
|
+-----------------------+ +-----------------------+
| Memento | | Caretaker |
+-----------------------+ +-----------------------+
| - state: String | | - memento: Memento |
| + GetState(): String | +-----------------------+
+-----------------------+
3 示例代码
假设我们要实现一个简单的文本编辑器,它能够保存文本的状态,并在需要时撤销或恢复状态。
原发器
csharp
// 原发器类
public class TextEditor
{
private string _text;
public void SetText(string text)
{
_text = text;
}
public string GetText()
{
return _text;
}
public Memento CreateMemento()
{
return new Memento(_text);
}
public void RestoreMemento(Memento memento)
{
_text = memento.GetState();
}
}
备忘录
csharp
// 备忘录类
public class Memento
{
private readonly string _state;
public Memento(string state)
{
_state = state;
}
public string GetState()
{
return _state;
}
}
负责人
csharp
// 负责人类
public class Caretaker
{
private readonly Stack<Memento> _mementos = new Stack<Memento>();
public void SaveMemento(Memento memento)
{
_mementos.Push(memento);
}
public Memento GetMemento()
{
if (_mementos.Count > 0)
{
return _mementos.Pop();
}
return null;
}
}
客户端代码
csharp
class Program
{
static void Main(string[] args)
{
TextEditor editor = new TextEditor();
Caretaker caretaker = new Caretaker();
editor.SetText("Version 1");
caretaker.SaveMemento(editor.CreateMemento());
editor.SetText("Version 2");
caretaker.SaveMemento(editor.CreateMemento());
editor.SetText("Version 3");
Console.WriteLine("Current Text: " + editor.GetText());
editor.RestoreMemento(caretaker.GetMemento());
Console.WriteLine("Restored Text: " + editor.GetText());
editor.RestoreMemento(caretaker.GetMemento());
Console.WriteLine("Restored Text: " + editor.GetText());
}
}
运行结果
plaintext
Current Text: Version 3
Restored Text: Version 2
Restored Text: Version 1
在这个例子中,TextEditor
是原发器,负责创建和恢复文本的状态;Memento
是备忘录,保存文本的状态;Caretaker
是负责人,管理备忘录的存储和恢复。在运行过程中,我们保存了多个文本状态,并通过恢复操作撤销了修改,返回到之前的状态。
6 特点
-
优点:
-
封装性: 备忘录模式保证了原发器状态的封装性,外部对象无法直接访问备忘录的内容。
-
状态恢复: 允许对象恢复到之前的状态,提供了实现"撤销/恢复"功能的简单方法。
-
简化复杂性: 通过将状态的存储和恢复职责分离到不同的类中,简化了复杂系统的管理。
-
-
缺点:
-
开销大: 如果原发器的状态占用大量资源(如内存),备忘录模式可能会导致开销较大,尤其是在频繁保存和恢复状态时。
-
管理复杂: 如果备忘录数量众多,管理这些备忘录可能变得复杂,尤其是在涉及多线程操作时。
-
7 适用场景
- 实现撤销/恢复功能: 当需要实现"撤销/恢复"操作时,备忘录模式非常适用。
- 需要记录历史状态: 在需要保存和恢复对象的多个历史状态的场景中,可以使用备忘录模式。
- 简化复杂对象的状态管理: 在复杂对象状态变化频繁且需要保证状态一致性的情况下,备忘录模式提供了一种有效的管理方式。
8 总结
备忘录模式通过保存对象的状态,提供了恢复该状态的机制。它通过封装状态,确保了对象内部细节的保护,同时又允许状态的恢复。该模式非常适合用于实现"撤销/恢复"功能,并在需要管理复杂状态变更的场景中提供了很好的解决方案。