Thursday, December 6, 2012

Design Patterns-Memento Pattern

備忘錄模式-在這如果我想做一個遊戲,以RPG來說,在進入遊戲戰鬥時我可以讓玩家選擇重新開始這場戰鬥,就像FFXIII玩家可以在戰鬥中隨時重新挑戰怪物更高分數、不同打法,

那該如何儲存腳色能力?

MementoPatterns_thumb1

GameRole.cs:

   1: class GameRole
   2: {
   3:     private int hp;
   4:     public int HP
   5:     {
   6:         set{hp = value;}
   7:         get{return hp;}
   8:     }
   9: }
  10: public void StateDisplay()
  11: {
  12:     Console.WriteLine("Now");
  13:     Console.WriteLine("HP:{0}",this.hp);
  14: }
  15: public void GetInitialize()
  16: {
  17:     this.hp = 100;
  18: }
  19: public void End()
  20: {
  21:     this.hp = 50;
  22: }
  23:  
  24: static void Main(string[] args)
  25: {
  26:   GameRole playerRole = new GameRole();
  27:   
  28:   //Game Initialize
  29:   playerRole.GetInitialize();
  30:   playerRole.StateDisplay();
  31:   
  32:   //Enter a battle : Record Play's Val
  33:   GameRole backup = new GameRole();
  34:   playerRole.HP = backup.HP; //出現物件細節,Not good
  35:  
  36:   //Battle is done
  37:   playRole.End()
  38:   playRole.StateDisplay();
  39:  
  40:  
  41:   // I want Re battle
  42:   playerRole.HP = backup.HP; //出現物件細節,Not good
  43:   playRole.StateDisplay();
  44:   
  45:   Console.Read();
  46: }
 
 

Memento Patterns:在不破壞封裝性的前提下,讀取一個物件的內部狀態,並在該物件之外保存這個狀態。可以讓物件回復到原先狀態保存狀態。


MementoPatterns1_thumb5


PlayerStateManager:根據狀態負責建立PlayerRecordManager,並同時記錄內部狀態,讓它可以用PlayerRecordManager回復狀態,StateManager可以決定RecordManager該存那些值與狀態。


PlayerRecordManager:負責存StateManager所需要的狀態與值,並防止其他物件存取RecordManager。RecordManager有兩個介面:


1.只能看到StateManager的窄介面,只能將值傳遞出去。


2.StateManager可以看到一個寬介面,允許存取恢復到先前的值。


PlayerRecorder:負責保存RecordManager,不能對其做任何檢查或操作。


其PlayerStateManager.cs:



   1: class PlayerStateManager()
   2: {
   3:   private string state;
   4:   public string State
   5:   {
   6:    get{return state;}
   7:    set{state = value;}
   8:   }
   9:   public PlayerRecordManager CreatePlayerRecordManager()
  10:   {
  11:     return (new PlayerRecordManager(state));
  12:   }
  13:   public void SetPlayerRecordManager(PlayerRecordManager recordManager)
  14:   {
  15:    state = recordManager.State;
  16:   }
  17:   public void Show()
  18:   {
  19:    //write out "State="+ state
  20:   }
  21: }
PlayerRecordManager.cs:


   1: class PlayerRecordManager
   2: {
   3:   private string state;
   4:   public PlayerRecordManager(string state)
   5:   {
   6:     this.state = state;
   7:   }
   8:   public string State
   9:   {
  10:    get{return state;}
  11:   }
  12: }PlayerRecorder.cs:
  13:  
  14: class PlayerRecorder
  15: {
  16:   private PlayerRecordManager playerRecordManager;
  17:   
  18:   public PlayerRecordManager PlayerRecordManager
  19:   {
  20:    get{return playerRecordManager;}
  21:    set{playerRecordManager = value;}
  22:   }
  23: }
PlayerRecorder.cs:


   1: class PlayerRecorder
   2: {
   3:   private PlayerRecordManager playerRecordManager;
   4:   
   5:   public PlayerRecordManager PlayerRecordManager
   6:   {
   7:    get{return playerRecordManager;}
   8:    set{playerRecordManager = value;}
   9:   }
  10: }




保存細節的目的是為了將細節封裝後,當需要更改保存細節時也不會影響到客戶端。


適用:


1.功能比較複雜但需要維護或記錄屬性歷史的類別。


2.需要保存的屬性只是眾多屬性中的一小部分,PlayerStateManager可以根據保存的PlayerRecordManager資訊還原到前一狀態。


缺點:
1.如果狀態資料很大量,在資源消耗上會非常耗記憶體。





   1: class PlayerStateManager()
   2: {
   3:   //........
   4:   public PlayerRecordManager SaveState()
   5:   {
   6:     return (new PlayerRecordManager(hp));
   7:   }
   8:   public void RecovertState(PlayerRecordManager recordManager)
   9:   {
  10:    this.hp = recordManager.HP;
  11:   }
  12:   //..........
  13: }


   1: class PlayerRecordManager
   2: {
   3:   private int hp;
   4:   public PlayerRecordManager(int hp)
   5:   {
   6:     this.hp = hp;
   7:   }
   8:   public int HP
   9:   {
  10:    set{hp = value;}
  11:    get{return hp;}
  12:   }
  13: }


   1: class PlayerRecorder
   2: {
   3:   private PlayerRecordManager playerRecordManager;
   4:   
   5:   public PlayerRecordManager PlayerRecordManager
   6:   {
   7:    get{return playerRecordManager;}
   8:    set{playerRecordManager = value;}
   9:   }
  10: }


   1: static void Main(string[] args)
   2: {
   3:   PlayerStateManager player =  new PlayerStateManager();
   4:   
   5:   player.GetInitState();
   6:   player.StateDisplay();
   7:  
   8:   //Backup State
   9:   PlayerRecorder stateAdmin = new PlayerRecorder();
  10:   stateAdmin.PlayerRecordManager = player.SaveState();
  11:   
  12:   player.End();
  13:   player.StateDisplay();
  14:    
  15:   player.RecoveryState(stateAdmin.PlayerRecordManager);
  16:   player.stateDisplay();
  17:   Console.Read();
  18: }

No comments:

Post a Comment