備忘錄模式/Memento

備忘錄模式/Memento

意圖/適用場景:
備忘錄對象是一個用來存儲另外一個對象內部狀態的快照的對象。
備忘錄模式的用意是在不破壞封裝的條件下,將一個對象的狀態捕捉住,並存儲起來。在將來合適的時候把這個對象還原到存儲時的狀態。

UML:

備忘錄模式/Memento

參與者:

  1. 發起人(Originator):需要保存自身狀態的對象。它有兩個功能,一是創建新的備忘錄,一是恢復到已有的備忘錄。
  2. 管理者(Caretaker):負責管理備忘錄,最主要的功能有兩個:一是把備忘錄存儲起來,一是從存儲設備中讀取備忘錄。
  3. 備忘錄接口(Memento):備忘錄的公共接口,不提供任何方法。
  4. 備忘錄寬接口(MementoWideIF):這一接口是給Originator使用的,主要面向狀態管理的功能,提供讀寫狀態的方法。
  5. 備忘錄窄接口(MementoNarrowIF):這一接口是給Caretaker使用的,主要面向存儲功能,提供序列化的方法。
  6. 具體備忘錄(ConcreteMemento):同時實現寬窄兩個接口,同時提供狀態讀寫和序列化的功能。

要點:
本模式裏一個關鍵的地方在於ConcreteMemento角色同時實現了MementoWideIF和MementoNarrowIF兩個接口。之所以這樣設計是出於接口隔離的考慮。Originator即狀態的使用者不關心備忘錄如果被存儲;而管理者也不應該看到與狀態有關的細節,它只關心備忘錄的存儲。所以最好讓它們分別面向不同的接口,互相不知道另一方以及另一套接口的存在。

應用實例:
電視遊戲中的save/load功能是一個很好的例子。當玩家保存遊戲進度時,就相當於建立了一份備忘錄並把它存儲起來,當然玩家可以建立不只一份的備忘錄。
當再次遊戲時,可以從已保存的多個進度中選擇一個,繼續遊戲,這時就相當於把遊戲場景恢復到保存時的狀態。

示例代碼:

   [java]
// Source code from file:  Caretaker.java

package designPatterns.Memento;

public class Caretaker {

public void saveMemento(Memento m) {
MementoNarrowIF mn = (MementoNarrowIF)m;
mn.serialize();
}

public Memento loadMemento() {
// This is just for demo.
// Caretaker don't know ConcreteMemento. It just get a Memento from other place.
return new ConcreteMemento();
}

}

// Source code from file:  ConcreteMemento.java

package designPatterns.Memento;

public class ConcreteMemento implements MementoWideIF, MementoNarrowIF {

private int state = 0;

public int getState() {
return state;
}

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

public void serialize() {
System.out.println("Memento was serialized.");
}

}

// Source code from file:  Memento.java

package designPatterns.Memento;

public interface Memento {

}

// Source code from file:  MementoNarrowIF.java

package designPatterns.Memento;

public interface MementoNarrowIF extends Memento {
public void serialize();
}

// Source code from file:  MementoWideIF.java

package designPatterns.Memento;

public interface MementoWideIF extends Memento {
public void setState(int state);
public int getState();
}

// Source code from file:  Originator.java

package designPatterns.Memento;

public class Originator {

private int state = 0;

public Memento createMemento() {
ConcreteMemento m = new ConcreteMemento();
m.setState(state);
System.out.println("create memento with state "  state);
return m;
}

public void restoreMemento(Memento m) {
MementoWideIF mw = (ConcreteMemento)m;
state = mw.getState();
System.out.println("restore memento with state "  state);
}
}

// Source code from file:  User.java

package designPatterns.Memento;

public class User {
public static void main(String[] args) {
Originator o = new Originator();
Caretaker c = new Caretaker();
// save memento
Memento m = o.createMemento();
c.saveMemento(m);
// load memento
m = c.loadMemento();
o.restoreMemento(m);
}
}
[/java]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章