Memento パターン

「Memento」という英単語は、「形見・記念」を意味します。

このパターンは、あるオブジェクトの任意の時点の状態を覚えておき(保存)、 後でその状態にオブジェクトを戻すための工夫を提供するパターンです。(カプセル化を破壊せずに、状態を元に戻せる)つまり、テキストエディタ等で実装されているような「アンドゥ」(操作をキャンセルして操作前の状態に戻す)機能を提供するためのパターンです。

注意すべきことは状態を元に戻すための必要最小限の情報(フィールド値)のみを保存すると言うことです。


役割り

1. Originator(作成者)

自分の状態を保存した「Memento」を作成します。(createMemento)

また、要求された「Memento」に状態を戻します。(setMemento)

自身の状態を「Memento」として保持する・与えられた「Memento」から自身の状態を復元するという役割を担います。

2. Memento(形見・記念品)
「Originator」の内部情報(フィールド値)を保持します。「Memento」は「Originator」と親密な関係にあります。(内部情報にアクセス)
3. Caretaker(世話人)

「Originator」の状態を保存したい場合・ある時点に戻したい場合は、「Originator」に指示を出します。保存するように指示をだした場合は、その時点の状態の「Memento」を受取り、保持します。(履歴の管理も可能)

「Memento」を保持するタイミング・アンドゥするタイミング・「Memento」を保持するという役割を担います。

▲PageTop

クラス図

Mementoパターンのクラス図

Mementoパターン クラス図

▲PageTop

サンプル

ソースコード

1. Originator.java

public class Originator {
    private int param1;
    private String param2;
    public Originator(int param1, String param2) {
        this.param1 = param1;
        this.param2 = param2;
    }
    public void calcAdd(int addNum) {
        param1 += addNum;
    }
    public void concat(String addStr) {
        param2 = param2 + addStr;
    }
    public Memento createMemento() {
        return new Memento(param1, param2);
    }
    public void setMemento(Memento memento) {
        this.param1 = memento.param1;
        this.param2 = memento.param2;
    }
    public String toString() {
        return "param1=>" + param1 + " / param2=>" + param2;
    }
}

2. Memento.java

public class Memento {
    int param1;
    String param2;
    Memento(int param1, String param2) {
        this.param1 = param1;
        this.param2 = param2;
    }
}

3. Caretaker.java

import java.util.Stack;

public class Caretaker {
    static Stack<Memento> mementoList = new Stack<Memento>();
    public static void main(String[] args) {
        Originator originator = new Originator(0, "");
        for (int i = 0; i < 5; i++) {
            for (int j = i; j < i + 5; j++) {
                originator.calcAdd(j);
                originator.concat(Integer.toString(j));
            }
            mementoList.push(originator.createMemento());
        }
        originator.calcAdd(5);
        originator.concat(Integer.toString(5));
        System.out.println(originator);
        while (mementoList.size() != 0) {
            Memento memento = (Memento) mementoList.pop();
            originator.setMemento(memento);
            System.out.println(originator);
        }
    }
}

実行結果

C:\sample\desin_pattern\memento>javac Client.java [Enter]

C:\sample\desin_pattern\memento>java Client [Enter]
param1=>105 / param2=>01234123452345634567456785
param1=>100 / param2=>0123412345234563456745678
param1=>70 / param2=>01234123452345634567
param1=>45 / param2=>012341234523456
param1=>25 / param2=>0123412345
param1=>10 / param2=>01234
        

▲PageTop