备忘录模式(17)
今天,我們來講備忘錄模式
一、案例:
小伙伴們都玩過單機游戲或者說RPG類的游戲吧,我們在打BOSS之前,需要先存一下檔,以免BOSS打不過從頭再來,好,下面,我們用簡單的控制臺應用程序來描述一下這個場景。
1 /// <summary> 2 /// 游戲角色類 3 /// </summary> 4 class GameRole 5 { 6 //生命值 7 private int vit; 8 9 public int Vit 10 { 11 get 12 { 13 return vit; 14 } 15 16 set 17 { 18 vit = value; 19 } 20 } 21 //攻擊力 22 private int atk; 23 public int Def 24 { 25 get 26 { 27 return def; 28 } 29 30 set 31 { 32 def = value; 33 } 34 } 35 private int def; 36 //防御力 37 public int Atk 38 { 39 get 40 { 41 return atk; 42 } 43 44 set 45 { 46 atk = value; 47 } 48 } 49 //狀態(tài)顯示 50 public void StateDisplay() 51 { 52 Console.WriteLine("角色當前狀態(tài):"); 53 Console.WriteLine($"體力:{this.vit}"); 54 Console.WriteLine($"攻擊力:{this.atk}"); 55 Console.WriteLine($"防御力:{this.def}"); 56 Console.WriteLine(""); 57 } 58 /// <summary> 59 /// 獲取初始狀態(tài) 60 /// 數(shù)據(jù)通常來自本機磁盤或遠程數(shù)據(jù)庫 61 /// </summary> 62 public void GetInitState() 63 { 64 this.vit = 100; 65 this.atk = 100; 66 this.def = 100; 67 } 68 /// <summary> 69 /// 戰(zhàn)斗 70 /// 在與Boss大戰(zhàn)后游戲數(shù)據(jù)損耗為0 71 /// </summary> 72 public void Fight() 73 { 74 this.vit = 0; 75 this.atk = 0; 76 this.def = 0; 77 } 78 }客戶端調(diào)用:
1 public static void Main() 2 { 3 //大戰(zhàn)Boss前 4 GameRole lixiaoyao = new GameRole(); 5 //大戰(zhàn)Boss前,獲得初始角色狀態(tài) 6 lixiaoyao.GetInitState(); 7 lixiaoyao.StateDisplay(); 8 9 //保存進度,通過‘游戲角色’的新實例來保存進度 10 GameRole backup = new GameRole(); 11 backup.Vit = lixiaoyao.Vit; 12 backup.Atk = lixiaoyao.Atk; 13 backup.Def = lixiaoyao.Def; 14 15 //大戰(zhàn)Boss 損耗很嚴重 16 lixiaoyao.Fight(); 17 lixiaoyao.StateDisplay(); 18 19 //恢復之前狀態(tài) 20 lixiaoyao.Vit = backup.Vit; 21 lixiaoyao.Atk = backup.Atk; 22 lixiaoyao.Def = backup.Def; 23 lixiaoyao.StateDisplay(); 24 Console.ReadKey(); 25 }好了,我們很好的描述了我們案例中的場景,那下面,我們看一下我們這段代碼有什么不足嗎?請看
//保存進度,通過‘游戲角色’的新實例來保存進度GameRole backup = new GameRole();backup.Vit = lixiaoyao.Vit;backup.Atk = lixiaoyao.Atk;backup.Def = lixiaoyao.Def; //恢復之前狀態(tài)lixiaoyao.Vit = backup.Vit;lixiaoyao.Atk = backup.Atk;lixiaoyao.Def = backup.Def;lixiaoyao.StateDisplay();這兩段代碼在客戶端暴露了細節(jié),客戶端的責任太多了,要知道角色的狀態(tài),還要備份,如果今后需要對角色增加 魔力值 這個屬性,那都是非常麻煩的事情了。
顯然,我們希望將角色的存取狀態(tài)細節(jié)封存起來,最好是封裝在外部的類當中,以體現(xiàn)職責分離。
面對上述的要求,這里,我們就需要學習一種新的設計模式了,備忘錄模式。
備忘錄模式:在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài),這樣就可以將對象恢復到原先保存的那個狀態(tài)。
好,下面我們來看一下設計模式的基本結(jié)構(gòu)代碼,需要三個類
?
1 /// <summary> 2 /// 發(fā)起人類 3 /// </summary> 4 class Originator 5 { 6 /// <summary> 7 /// 需要保存的屬性,可以是多個 8 /// </summary> 9 private string state; 10 11 public string State 12 { 13 get 14 { 15 return state; 16 } 17 18 set 19 { 20 state = value; 21 } 22 } 23 /// <summary> 24 /// 創(chuàng)建備忘錄,將當前需要保存的信息導入并實例化出一個Memento對象 25 /// </summary> 26 /// <returns></returns> 27 public Memento CraeteMemento() 28 { 29 return new Memento(state); 30 } 31 32 public void SetMemento(Memento memento) 33 { 34 state = memento.State; 35 } 36 /// <summary> 37 /// 顯示數(shù)據(jù) 38 /// </summary> 39 public void Show() 40 { 41 Console.WriteLine($"State={state}"); 42 } 43 } 44 /// <summary> 45 /// 備忘錄類 46 /// </summary> 47 class Memento 48 { 49 private string state; 50 /// <summary> 51 /// 構(gòu)造方法,將相關(guān)數(shù)據(jù)導入 52 /// </summary> 53 /// <param name="state"></param> 54 public Memento(string state) 55 { 56 this.state = state; 57 } 58 /// <summary> 59 /// 需要保存的數(shù)據(jù)屬性,可以是多個 60 /// </summary> 61 public string State 62 { 63 get { return state; } 64 } 65 } 66 /// <summary> 67 /// 管理者 68 /// </summary> 69 class Caretaker 70 { 71 /// <summary> 72 /// 屬性,得到或設置備忘錄 73 /// </summary> 74 private Memento memento; 75 76 internal Memento Memento 77 { 78 get 79 { 80 return memento; 81 } 82 83 set 84 { 85 memento = value; 86 } 87 } 88 }客戶端調(diào)用:
1 public static void Main() 2 { 3 //Originator 初始狀態(tài),狀態(tài)屬性為”O(jiān)n“ 4 Originator o = new Originator(); 5 o.State = "On"; 6 o.Show(); 7 8 //保存狀態(tài)時,由于有了很好的封裝,可以隱藏Originator的實現(xiàn)細節(jié) 9 Caretaker c = new Caretaker(); 10 c.Memento = o.CraeteMemento(); 11 12 //改變Originator狀態(tài)為”O(jiān)ff“ 13 o.State = "Off"; 14 o.Show(); 15 16 //恢復原始狀態(tài) 17 o.SetMemento(c.Memento); 18 o.Show(); 19 Console.ReadKey(); 20 }好,我們就用備忘錄模式來寫一下我們案例中的代碼
?
1 /// <summary> 2 /// 游戲角色類(發(fā)起者) 3 /// </summary> 4 class GameRole 5 { 6 //生命值 7 private int vit; 8 9 public int Vit 10 { 11 get 12 { 13 return vit; 14 } 15 16 set 17 { 18 vit = value; 19 } 20 } 21 //攻擊力 22 private int atk; 23 public int Def 24 { 25 get 26 { 27 return def; 28 } 29 30 set 31 { 32 def = value; 33 } 34 } 35 private int def; 36 //防御力 37 public int Atk 38 { 39 get 40 { 41 return atk; 42 } 43 44 set 45 { 46 atk = value; 47 } 48 } 49 //狀態(tài)顯示 50 public void StateDisplay() 51 { 52 Console.WriteLine("角色當前狀態(tài):"); 53 Console.WriteLine($"體力:{this.vit}"); 54 Console.WriteLine($"攻擊力:{this.atk}"); 55 Console.WriteLine($"防御力:{this.def}"); 56 Console.WriteLine(""); 57 } 58 /// <summary> 59 /// 獲取初始狀態(tài) 60 /// 數(shù)據(jù)通常來自本機磁盤或遠程數(shù)據(jù)庫 61 /// </summary> 62 public void GetInitState() 63 { 64 this.vit = 100; 65 this.atk = 100; 66 this.def = 100; 67 } 68 /// <summary> 69 /// 戰(zhàn)斗 70 /// 在與Boss大戰(zhàn)后游戲數(shù)據(jù)損耗為0 71 /// </summary> 72 public void Fight() 73 { 74 this.vit = 0; 75 this.atk = 0; 76 this.def = 0; 77 } 78 /// <summary> 79 /// 保存角色狀態(tài) 80 /// </summary> 81 /// <returns></returns> 82 public RoleStateMemtento SaveState() 83 { 84 return new RoleStateMemtento(vit, atk, def); 85 } 86 /// <summary> 87 /// 恢復角色狀態(tài) 88 /// </summary> 89 /// <param name="memento"></param> 90 public void RecoverState(RoleStateMemtento memento) 91 { 92 this.vit = memento.Vit; 93 this.atk = memento.Atk; 94 this.def = memento.Def; 95 } 96 } 97 /// <summary> 98 /// 角色狀態(tài)儲存箱(備忘錄) 99 /// </summary> 100 class RoleStateMemtento 101 { 102 private int vit; 103 private int atk; 104 private int def; 105 106 public int Vit 107 { 108 get 109 { 110 return vit; 111 } 112 113 set 114 { 115 vit = value; 116 } 117 } 118 119 public int Atk 120 { 121 get 122 { 123 return atk; 124 } 125 126 set 127 { 128 atk = value; 129 } 130 } 131 132 public int Def 133 { 134 get 135 { 136 return def; 137 } 138 139 set 140 { 141 def = value; 142 } 143 } 144 /// <summary> 145 /// 將生命力,攻擊力,防御力 存入狀態(tài)存儲箱對象中 146 /// </summary> 147 /// <param name="vit"></param> 148 /// <param name="atk"></param> 149 /// <param name="def"></param> 150 public RoleStateMemtento(int vit, int atk, int def) 151 { 152 this.vit = vit; 153 this.atk = atk; 154 this.def = def; 155 } 156 } 157 /// <summary> 158 /// 管理者 159 /// </summary> 160 class RoleStateCaretaker 161 { 162 private RoleStateMemtento memento; 163 164 internal RoleStateMemtento Memento 165 { 166 get 167 { 168 return memento; 169 } 170 171 set 172 { 173 memento = value; 174 } 175 } 176 }客戶端調(diào)用:
1 public static void Main() 2 { 3 //大戰(zhàn)Boss前 4 //游戲角色初始狀態(tài),三項指標都為100 5 GameRole lixiaoyao = new GameRole(); 6 lixiaoyao.GetInitState(); 7 lixiaoyao.StateDisplay(); 8 9 //保存進度 10 //保存進度時,由于封裝在Memento中,因此,我們并不知道保存了哪些具體的角色數(shù)據(jù) 11 RoleStateCaretaker stateAdmin = new RoleStateCaretaker(); 12 stateAdmin.Memento = lixiaoyao.SaveState(); 13 14 //大戰(zhàn)Boss,損耗嚴重 15 //三項指標都為0,GameOver了。 16 lixiaoyao.Fight(); 17 lixiaoyao.StateDisplay(); 18 19 //恢復之前狀態(tài) 20 lixiaoyao.RecoverState(stateAdmin.Memento); 21 lixiaoyao.StateDisplay(); 22 Console.ReadKey(); 23 }好了,今天備忘錄模式就講到這里,下一篇博文,我們講 組合模式
本系列將持續(xù)更新,喜歡的小伙伴可以點一下關(guān)注和推薦,謝謝大家的支持
轉(zhuǎn)載于:https://www.cnblogs.com/xiaomowang/p/6372887.html
總結(jié)
- 上一篇: 2017寒假练习题解 第四周 2.6-2
- 下一篇: CI配置文件 --------- aut