什么是备忘录模式?
备忘录模式(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信息还原到前一状态。
备注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。