「Memento」という英単語は、「形見・記念」を意味します。
このパターンは、あるオブジェクトの任意の時点の状態を覚えておき(保存)、 後でその状態にオブジェクトを戻すための工夫を提供するパターンです。(カプセル化を破壊せずに、状態を元に戻せる)つまり、テキストエディタ等で実装されているような「アンドゥ」(操作をキャンセルして操作前の状態に戻す)機能を提供するためのパターンです。
注意すべきことは状態を元に戻すための必要最小限の情報(フィールド値)のみを保存すると言うことです。
自分の状態を保存した「Memento」を作成します。(createMemento)
また、要求された「Memento」に状態を戻します。(setMemento)
自身の状態を「Memento」として保持する・与えられた「Memento」から自身の状態を復元するという役割を担います。
「Originator」の状態を保存したい場合・ある時点に戻したい場合は、「Originator」に指示を出します。保存するように指示をだした場合は、その時点の状態の「Memento」を受取り、保持します。(履歴の管理も可能)
「Memento」を保持するタイミング・アンドゥするタイミング・「Memento」を保持するという役割を担います。
Mementoパターンのクラス図
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