文章

備忘錄模式 - Memento Pattern

用途

管理物件狀態的存取

classDiagram
  note for Client "Originator modify content save to Memento\n MementoManager manage Memento"
  MementoManager --> Memento
  Originator --> Memento
  Client --> MementoManager
  Client --> Originator
  class Memento{
    +string content
    +Memento(string content)
  }
  class MementoManager{
    -Stack<Memento> _mementos
    +Save(Memento memento)
    +Restore() Memento
  }
  class Originator{
    -string _content
    +SetContent(string content)
    +CreateMemento() Memento
    +RestoreFromMemento(Memento memento)
    +Render()
  }
  class Client{
    +Operation()
  }

例子

當談到備忘錄模式(Memento Pattern)時,我們可以以一個文字編輯器的例子來解釋

假設你正在使用一個文字編輯器來編寫一份文件,你希望能夠隨時保存編輯的進度,並在需要的時候恢復到之前的狀態
這就是備忘錄模式的應用場景

在這個例子中,文字編輯器是原發器(Originator),而文件的狀態則被稱為備忘錄(Memento)
備忘錄將保存原發器的內部狀態,以便在需要時可以恢復

原發器(TextEditor)負責設置和打印文件的內容,以及創建和恢復備忘錄
備忘錄管理者(MementoManager)負責保存和彈出備忘錄

通過使用備忘錄模式,我們可以隨時保存編輯器的狀態並恢復到先前的狀態
這在需要追蹤或撤銷操作時非常有用

Memento

1
2
3
4
5
6
7
8
9
10
// 備忘錄類別,保存原發器的狀態
public class Memento
{
    public string Content { get; }

    public Memento(string content)
    {
        Content = content;
    }
}

MementoManager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 備忘錄管理者類別,負責保存和恢復備忘錄
public class MementoManager
{
    private Stack<Memento> _mementos = new Stack<Memento>();

    public void SaveMemento(Memento memento)
    {
        _mementos.Push(memento);
    }

    public Memento PopMemento()
    {
        return _mementos.Pop();
    }
}

Originator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 原發器類別,負責創建和恢復備忘錄
public class TextEditor
{
    private string _content;

    public void SetContent(string content)
    {
        _content = content;
    }

    public Memento CreateMemento()
    {
        return new Memento(_content);
    }

    public void RestoreFromMemento(Memento memento)
    {
        _content = memento.Content;
    }

    public void PrintContent()
    {
        Console.WriteLine($"Current Content: {_content}");
    }
}

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 使用範例
TextEditor textEditor = new TextEditor();
MementoManager mementoManager = new MementoManager();

textEditor.SetContent("This is the initial content.");
textEditor.PrintContent();

// 保存備忘錄
Memento initialMemento = textEditor.CreateMemento();
mementoManager.SaveMemento(initialMemento);

// 進行編輯操作
textEditor.SetContent("This is the updated content.");
textEditor.PrintContent();

// 恢復到之前的狀態
Memento restoredMemento = mementoManager.PopMemento();
textEditor.RestoreFromMemento(restoredMemento);
textEditor.PrintContent();

延伸

本文章以 CC BY 4.0 授權