備忘錄模式的用途很單純,就是提供物件回到之前狀態的功能,簡單說就是備份 (存檔) 的機制。備忘錄模式是一個在現實世界中很常使用到的模式,如遊戲的儲存記錄,文書編輯器的「上一步」功能等。簡單介紹完這個模式後,就來看一下正式的定義及類別圖吧:
參考資料:
深入淺出設計模式(Head First Design Patterns)
不違反封裝的情形下,取得物件的內部狀態。如此可以回復物件之前的狀態。
Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.
- Originator:就是定義中提到的要保留內部狀態的物件。現實例子就像是遊戲角色狀態,或是文書編輯器中的文字等。
- Memento:保留 Originator 內部狀態 (資料) 的物件,例如遊戲中要存檔的資料。
- Caretaker:主要功用是管理 Memento 物件。
看到這邊,我們應該能知道備忘錄模式有兩個目標:
- 儲存物件的重要狀態
- 維護物件的封裝
// Originator
public class GamePlayer {
// 遊戲角色的生命值
private int mHp;
// 遊戲角色的經驗值
private int mExp;
public GamePlayer(int hp, int exp)
{
mHp = hp;
mExp = exp;
}
public GameMemento saveToMemento()
{
return new GameMemento(mHp, mExp);
}
public void restoreFromMemento(GameMemento memento)
{
mHp = memento.getGameHp();
mExp = memento.getGameExp();
}
public void play(int hp, int exp)
{
mHp = mHp - hp;
mExp = mExp + exp;
}
}
// Memento
public class GameMemento {
// 假設只有這兩個資料要保留
private int mGameHp;
private int mGameExp;
public GameMemento(int hp, int exp)
{
mGameHp = hp;
mGameExp = exp;
}
public int getGameHp()
{
return mGameHp;
}
public int getGameExp()
{
return mGameExp;
}
}
// Caretaker
public class GameCaretaker {
// 保留要處理的資料。
// 這邊只是範例,所以 Caretaker
// 只能處理一個 Memento。
// 實務上當然可以用更複雜的結構來
// 處理多個 Memento,如 ArrayList。
private GameMemento mMemento;
public GameMemento getMemento()
{
return mMemento;
}
public void setMemento(GameMemento memento)
{
mMemento = memento;
}
}
public class Demo {
public static void main(String[] args)
{
// 創造一個遊戲角色
GamePlayer player = new GamePlayer(100, 0);
// 先存個檔
GameCaretaker caretaker = new GameCaretaker();
caretaker.setMemento(player.seveToMemento());
// 不小心死掉啦
player.play(-100, 10);
// 重新讀取存檔,又是一尾活龍
player.restoreFromMemento(caretaker.getMemento());
}
}
最後來總結一下吧。備忘錄模式的用途就是提供備份功能,因此這個模式的架構本身就設計的容易實作復原功能。也因為拆成了 Originator,Memento,Caretaker,除了讓物件的資料封裝不被破壞外,也提高了內聚力 (cohesion)。雖然範例的備份復原很簡單,但實務上 Memento 要保留的資料可能很多,會造成備份還原的時間很長,這是要注意的部份。另外,Java SDK 本身的 Serializable 以及 Android SDK 的 Parcelable 都算是很好的備忘錄模式實作,有興趣的人可以參考。參考資料:
深入淺出設計模式(Head First Design Patterns)

留言
張貼留言