设计模式 18 备忘录模式

设计模式 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 总结

备忘录模式通过保存对象的状态,提供了恢复该状态的机制。它通过封装状态,确保了对象内部细节的保护,同时又允许状态的恢复。该模式非常适合用于实现"撤销/恢复"功能,并在需要管理复杂状态变更的场景中提供了很好的解决方案。

相关推荐
杨充19 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充19 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充19 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充19 小时前
2.面向对象的特性
设计模式
杨充19 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充19 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充19 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式