「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