備忘錄模式

📢 本文由 gemini-3-flash-preview 翻譯

Memento Pattern 物件行為型模式

意圖

在不破壞封裝性的前提下擷取一個物件的內部狀態,並在物件之外儲存這個狀態。這樣以後就可以將物件恢復到原先儲存的狀態

結構

備忘錄模式

其中:

  • Memento (備忘錄) 儲存原發器物件的內部狀態,原發器根據需要決定備忘錄儲存原發器的哪些內部狀態;防止原發器以外的其他物件存取備忘錄
  • Originator (原發器) 建立一個備忘錄,用於記錄目前時刻它的內部狀態;使用備忘錄恢復內部狀態
  • Caretaker (管理者) 負責保存好備忘錄;不能對備忘錄的內容進行操作或檢查

適用性

Memento 模式適用於:

  • 必須儲存一個物件在某一個時刻的 (部分) 狀態,這樣以後需要時它才能恢復到先前的狀態
  • 如果用介面來讓其他物件直接得到這些狀態,將會暴露物件的實作細節並破壞物件的封裝性

範例

 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.util.ArrayList;
import java.util.List;

public class MementoPattern {
    public static void main(String[] args) {
        Caretaker caretaker = new Caretaker();
        Originator originator = new Originator();

        originator.setState("first");
        Memento memento1 = originator.createMemento();
        caretaker.addMemento(memento1);

        originator.setState("second");
        Memento memento2 = originator.createMemento();
        caretaker.addMemento(memento2);

        originator.setState("third");
        Memento memento3 = originator.createMemento();
        caretaker.addMemento(memento3);

        caretaker.showMemento();

        Memento backup = caretaker.getMemento(2);
        originator.setMemento(backup);
        System.out.println("=========");
        System.out.println(originator.getState());

    }
}

class Originator{ // 原發器
    private String state;

    public void setState(String state){
        this.state = state;
    }

    public String getState(){
        return state;
    }

    public Memento createMemento(){
        return new Memento(state);
    }

    public void setMemento(Memento memento){
        state = memento.getState();
    }
}

class Memento{ // 備忘錄
    private String state;

    public Memento(String state){
        this.state = state;
    }

    public String getState(){
        return state;
    }
}

class Caretaker{ // 管理者
    private List<Memento> mementoList = new ArrayList<>();

    public void addMemento(Memento memento){
        mementoList.add(memento);
    }

    public Memento getMemento(int index){
        return mementoList.get(index - 1);
    }

    public void showMemento(){
        int i = 1;
        for(Memento m : mementoList){
            System.out.println("No." + i + ": " + m.getState());
            i++;
        }
    }
}