什麼是備忘錄模式? 備忘錄模式(Memento):在不破壞封裝的前提下,捕獲一個對象的內部狀態,併在該對象之外保存這個狀態。 這樣以後就可將該對象恢復到原先保存的狀態。 備忘錄模式的組成 Originator(發起人):負責創建一個備忘錄Memento,用以記錄當前時刻它的內部狀態,並可使用備忘錄恢 ...
什麼是備忘錄模式?
備忘錄模式(Memento):在不破壞封裝的前提下,捕獲一個對象的內部狀態,併在該對象之外保存這個狀態。
這樣以後就可將該對象恢復到原先保存的狀態。
備忘錄模式的組成
Originator(發起人):負責創建一個備忘錄Memento,用以記錄當前時刻它的內部狀態,並可使用備忘錄恢復內部狀態。
Originator可根據需要決定Memento存儲Originator的哪些內部狀態。
Memento(備忘錄):負責存儲Originator對象的內部狀態,並可防止Originator以外的其他對象訪問Memento。
Memento有兩個介面,Caretaker只能看到備忘錄的窄介面,它只能將備忘錄傳遞給其他對象。
Originator能夠看到一個寬介面,允許它訪問返回到現錢狀態所需的所有數據。
Caretaker(管理者):負責保存好備忘錄Memento,不能對備忘錄的內容進行操作或者檢查。
備忘錄模式具體實現
適配器模式的結構
適配器模式的實現
Originator(發起人)類:
1 class Originator 2 { 3 private string state; 4 public string State 5 { 6 get { return state; } 7 set { state = value; } 8 } 9 public void Show() 10 { 11 Console.WriteLine("State={0}", State); 12 } 13 /// <summary> 14 /// 從memento中調用之前保存好的參數 15 /// </summary> 16 public void SetMemento(Memento memento) 17 { 18 this.state = memento.State; 19 } 20 /// <summary> 21 /// 將當前的參數記錄到Memento中去 22 /// </summary> 23 /// <returns></returns> 24 public Memento CreateMemento() 25 { 26 return (new Memento(state)); 27 } 28 }
Memento(備忘錄)類:
1 class Memento 2 { 3 private string state; 4 /// <summary> 5 /// 備忘錄中只需要變成只讀就可以了 6 /// </summary> 7 public string State 8 { 9 get { return state; } 10 } 11 public Memento(string state) 12 { 13 this.state = state; 14 } 15 }
Caretaker(管理者)類:
1 class Caretaker 2 { 3 private Memento memento; 4 public Memento Memento 5 { 6 get { return memento; } 7 set { memento = value; } 8 } 9 }
主函數調用
1 static void Main(string[] args) 2 { 3 //初始化Originator,設定初始數據 4 Originator o = new Originator(); 5 o.State = "O"; 6 o.Show(); 7 //保存Originator傳遞至Memento中 8 Caretaker c = new Caretaker(); 9 c.Memento = o.CreateMemento(); 10 //修改Originator中的數據 11 o.State = "T"; 12 o.Show(); 13 //調用備忘錄中數據,重新更新數據 14 o.SetMemento(c.Memento); 15 o.Show(); 16 17 Console.Read(); 18 }
實例解析
為了深化理解,我們準備一個具體的實例來分析。
在玩游戲的過程中,假設游戲有99關,我們從第1關開始,打到第15關的時候沒有成功,這是我們就需要保存保存當前的進度,不然下次進來的時候我們就又得從第一關重新開始了。
分析:
我們需要保存當前的進度,這隻是起到一個暫存的作用。
具體實現:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //創建一個英雄角色李逍遙 6 GameRole lixiaoyao = new GameRole(); 7 lixiaoyao.GetInitState(); 8 lixiaoyao.Show(); 9 //將李逍遙數據保存在備忘錄中 10 RoleStateCaretaker c = new RoleStateCaretaker(); 11 c.Menmento = lixiaoyao.SaveState(); 12 //讓李逍遙參與戰鬥 13 lixiaoyao.Fight(); 14 lixiaoyao.Show(); 15 //由於參與戰鬥後狀態都發生了變化,所以重新調用以前的數據 16 lixiaoyao.RecoverState(c.Menmento); 17 lixiaoyao.Show(); 18 19 Console.Read(); 20 } 21 class GameRole 22 { 23 private int vitality; 24 private int attack; 25 private int defense; 26 //生命力 27 public int Vitality 28 { 29 get { return vitality; } 30 set { vitality = value; } 31 } 32 //攻擊力 33 public int Attack 34 { 35 get { return attack; } 36 set { attack = value; } 37 } 38 //防禦力 39 public int Defense 40 { 41 get { return defense; } 42 set { defense = value; } 43 } 44 //獲取初始狀態 45 public void GetInitState() 46 { 47 this.vitality = 100; 48 this.defense = 100; 49 this.attack = 100; 50 } 51 //從Memento中獲取到剛剛保存的數據 52 public void RecoverState(RoleStateMemento memento) 53 { 54 this.vitality = memento.Vitality; 55 this.defense = memento.Defense; 56 this.attack = memento.Attack; 57 } 58 //保存當前數據到Memento中 59 public RoleStateMemento SaveState() 60 { 61 return (new RoleStateMemento(vitality, attack, defense)); 62 } 63 //顯示當前狀態 64 public void Show() 65 { 66 Console.WriteLine("State:"); 67 Console.WriteLine("vitality={0}", vitality); 68 Console.WriteLine("Attack={0}", attack); 69 Console.WriteLine("Defense={0}", Defense); 70 } 71 //參與戰隊導致狀態變得不好了 72 public void Fight() 73 { 74 this.vitality = 0; 75 this.attack = 0; 76 this.defense = 0; 77 } 78 } 79 class RoleStateMemento 80 { 81 private int vitality; 82 private int attack; 83 private int defense; 84 //生命力 85 public int Vitality 86 { 87 get { return vitality; } 88 set { vitality = value; } 89 } 90 //攻擊力 91 public int Attack 92 { 93 get { return attack; } 94 set { attack = value; } 95 } 96 //防禦力 97 public int Defense 98 { 99 get { return defense; } 100 set { defense = value; } 101 } 102 //當角色將數據傳遞過來的時候需要調用這個函數 103 public RoleStateMemento(int v,int a,int d) 104 { 105 this.vitality = v; 106 this.defense = d; 107 this.attack = a; 108 } 109 } 110 class RoleStateCaretaker 111 { 112 private RoleStateMemento memento; 113 public RoleStateMemento Menmento 114 { 115 get { return memento; } 116 set { memento = value; } 117 } 118 } 119 }
備忘錄模式的優缺點
Memento模式比較適用於功能比較複雜的,但是需要維護或者記錄屬性歷史的類,或者需要保存的屬性只是眾多屬性中的一個小部分時。Originator可以根據保存的Memento信息還原到前一狀態。
備註:文中所有代碼及知識點均來自於《大話設計模式》,本人屬於邊學邊看邊敲代碼邊總結的階段。