备忘录模式(17)

时间:2022-06-01 18:28:33

今天,我们来讲备忘录模式

一、案例:

小伙伴们都玩过单机游戏或者说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         //状态显示
50         public void StateDisplay()
51         {
52             Console.WriteLine("角色当前状态:");
53             Console.WriteLine($"体力:{this.vit}");
54             Console.WriteLine($"攻击力:{this.atk}");
55             Console.WriteLine($"防御力:{this.def}");
56             Console.WriteLine("");
57         }
58         /// <summary>
59         /// 获取初始状态
60         /// 数据通常来自本机磁盘或远程数据库
61         /// </summary>
62         public void GetInitState()
63         {
64             this.vit = 100;
65             this.atk = 100;
66             this.def = 100;
67         }
68         /// <summary>
69         /// 战斗
70         /// 在与Boss大战后游戏数据损耗为0
71         /// </summary>
72         public void Fight()
73         {
74             this.vit = 0;
75             this.atk = 0;
76             this.def = 0;
77         }
78     }

客户端调用:

 1         public static void Main()
 2         {
 3             //大战Boss前
 4             GameRole lixiaoyao = new GameRole();
 5             //大战Boss前,获得初始角色状态
 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             //大战Boss 损耗很严重
16             lixiaoyao.Fight();
17             lixiaoyao.StateDisplay();
18 
19             //恢复之前状态
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;
   //恢复之前状态
            lixiaoyao.Vit = backup.Vit;
            lixiaoyao.Atk = backup.Atk;
            lixiaoyao.Def = backup.Def;
            lixiaoyao.StateDisplay();

这两段代码在客户端暴露了细节,客户端的责任太多了,要知道角色的状态,还要备份,如果今后需要对角色增加 魔力值 这个属性,那都是非常麻烦的事情了。

显然,我们希望将角色的存取状态细节封存起来,最好是封装在外部的类当中,以体现职责分离。

面对上述的要求,这里,我们就需要学习一种新的设计模式了,备忘录模式。

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以将对象恢复到原先保存的那个状态。

好,下面我们来看一下设计模式的基本结构代码,需要三个类

 

 1     /// <summary>
 2     /// 发起人类
 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         /// 创建备忘录,将当前需要保存的信息导入并实例化出一个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         /// 显示数据
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         /// 构造方法,将相关数据导入
52         /// </summary>
53         /// <param name="state"></param>
54         public Memento(string state)
55         {
56             this.state = state;
57         }
58         /// <summary>
59         /// 需要保存的数据属性,可以是多个
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     }

客户端调用:

 1         public static void Main()
 2         {
 3             //Originator 初始状态,状态属性为”On“
 4             Originator o = new Originator();
 5             o.State = "On";
 6             o.Show();
 7 
 8             //保存状态时,由于有了很好的封装,可以隐藏Originator的实现细节
 9             Caretaker c = new Caretaker();
10             c.Memento = o.CraeteMemento();
11 
12             //改变Originator状态为”Off“
13             o.State = "Off";
14             o.Show();
15 
16             //恢复原始状态
17             o.SetMemento(c.Memento);
18             o.Show();
19             Console.ReadKey();
20         }

好,我们就用备忘录模式来写一下我们案例中的代码

 

  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         //状态显示
 50         public void StateDisplay()
 51         {
 52             Console.WriteLine("角色当前状态:");
 53             Console.WriteLine($"体力:{this.vit}");
 54             Console.WriteLine($"攻击力:{this.atk}");
 55             Console.WriteLine($"防御力:{this.def}");
 56             Console.WriteLine("");
 57         }
 58         /// <summary>
 59         /// 获取初始状态
 60         /// 数据通常来自本机磁盘或远程数据库
 61         /// </summary>
 62         public void GetInitState()
 63         {
 64             this.vit = 100;
 65             this.atk = 100;
 66             this.def = 100;
 67         }
 68         /// <summary>
 69         /// 战斗
 70         /// 在与Boss大战后游戏数据损耗为0
 71         /// </summary>
 72         public void Fight()
 73         {
 74             this.vit = 0;
 75             this.atk = 0;
 76             this.def = 0;
 77         }
 78         /// <summary>
 79         /// 保存角色状态
 80         /// </summary>
 81         /// <returns></returns>
 82         public RoleStateMemtento SaveState()
 83         {
 84             return new RoleStateMemtento(vit, atk, def);
 85         }
 86         /// <summary>
 87         /// 恢复角色状态
 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     /// 角色状态储存箱(备忘录)
 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         /// 将生命力,攻击力,防御力 存入状态存储箱对象中
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     }

客户端调用:

 1         public static void Main()
 2         {
 3             //大战Boss前
 4             //游戏角色初始状态,三项指标都为100
 5             GameRole lixiaoyao = new GameRole();
 6             lixiaoyao.GetInitState();
 7             lixiaoyao.StateDisplay();
 8 
 9             //保存进度
10             //保存进度时,由于封装在Memento中,因此,我们并不知道保存了哪些具体的角色数据
11             RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
12             stateAdmin.Memento = lixiaoyao.SaveState();
13 
14             //大战Boss,损耗严重
15             //三项指标都为0,GameOver了。
16             lixiaoyao.Fight();
17             lixiaoyao.StateDisplay();
18 
19             //恢复之前状态
20             lixiaoyao.RecoverState(stateAdmin.Memento);
21             lixiaoyao.StateDisplay();
22             Console.ReadKey();
23         }

好了,今天备忘录模式就讲到这里,下一篇博文,我们讲 组合模式


本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持