2013年7月12日 星期五

設計模式:備忘錄模式 (Memento Pattern)

備忘錄模式 (Memento Pattern),以下程式碼以 C# 為例

說明:
讓物件回復到之前狀態的方法。

範例:
一個遊戲,玩家有體力(HP)和經驗值(EXP)兩個屬性。
戰鬥後,HP 減少,EXP 增加。
可使用備忘錄模式的方法,將玩家的狀態,回復到戰鬥前。
(備忘錄模式,在棋類遊戲中的悔棋功能,似乎也用得到。)

希望達成如下的效果
static void Main(string[] args)
{
    Player aa = new Player();
    Console.WriteLine("[初始狀態]");
    Console.WriteLine("HP : {0}", aa.hp);
    Console.WriteLine("EXP : {0}", aa.exp);

    Caretaker aaCaretaker = new Caretaker(); // 新增資料管理者
    aaCaretaker.PlayerMemento = aa.saveToMemento(); // 儲存目前狀態

    aa.run(-80, 125); // 戰鬥,HP、EXP 改變
    Console.WriteLine("{0}[戰鬥後]", Environment.NewLine);
    Console.WriteLine("HP : {0}", aa.hp);
    Console.WriteLine("EXP : {0}", aa.exp);

    aa.loadFromMemento(aaCaretaker.PlayerMemento); // 回復到戰鬥前的狀態
    Console.WriteLine("{0}[回復到戰鬥前]", Environment.NewLine);
    Console.WriteLine("HP : {0}", aa.hp);
    Console.WriteLine("EXP : {0}", aa.exp);


    Console.ReadLine();
}
執行結果: 
[初始狀態]
HP : 100
EXP : 0

[戰鬥後]
HP : 20
EXP : 125

[回復到戰鬥前]
HP : 100
EXP : 0


實現重點在於,區分 Originator、Memento、Caretaker 三個物件
Originator 可將自己的狀態儲存在 Memento 中,
並將 Memento 保留在 Caretaker 裡面。
當 Originator 要回復狀態時,再從 Caretaker 取得 Memento 進行回復。

其餘程式碼
// 玩家 (Originator class)
class Player
{
    private int _hp = 100; // 體力
    private int _exp = 0; // 經驗值

    // 儲存資料
    public Memento saveToMemento()
    {
        // 將要儲存的資料傳給 Memento 物件
        return (new Memento(this._hp, this._exp));
    }

    // 回復資料
    public void loadFromMemento(Memento m)
    {
        this._hp = m.hp;
        this._exp = m.exp;
    }

    // 體力、經驗值 增減
    public void run(int hp, int exp)
    {
        this._hp += hp;
        this._exp += exp;
    }

    public int hp
    {
        get { return this._hp; }
        set { this._hp = value; }
    }

    public int exp
    {
        get { return this._exp; }
        set { this._exp = value; }
    }

}

// 儲存資料
class Memento
{
    private int _hp;
    private int _exp;

    public Memento(int hp, int exp)
    {
        this.hp = hp;
        this.exp = exp;
    }

    public int hp
    {
        get { return this._hp; }
        set { this._hp = value; }
    }

    public int exp
    {
        get { return this._exp; }
        set { this._exp = value; }
    }

}

// 資料管理者
class Caretaker
{
    private Memento _PlayerMemento;

    public Memento PlayerMemento
    {
        get { return _PlayerMemento; }
        set { _PlayerMemento = value; }
    }
}

相關連結:設計模式整理列表

沒有留言:

張貼留言