备忘录模式(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         //状态显示
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         }

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



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

时间: 2024-10-16 14:56:09

备忘录模式(17)的相关文章

设计模式之第17章-备忘录模式(Java实现)

设计模式之第17章-备忘录模式(Java实现) 好男人就是我,我就是曾小贤.最近陈赫和张子萱事件闹得那是一个沸沸扬扬.想想曾经每年都有爱情公寓陪伴的我现如今过年没有了爱情公寓总是感觉缺少点什么.不知道你们可曾记得爱情公寓里的一个经典的桥段~每次关谷和唐悠悠吵架的时候,总是可以进行“存档”,先干其他的事情,而后有时间的时候再继续“读档”,这是多么好的一个技能啊,想想吧,每次吵架,存档后可以做其他事情进行冷静一下,然后读档的时候已经冷静好了,是不是会清醒很多呢,是不是就不会有那么多的误会无法解除了呢

设计模式解密(17)- 备忘录模式

1.简介 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样就可以将该对象恢复到原先保存的状态. 解释:也就是说,不破坏源数据的情况下,将源数据进行一次或者多次的备份. 本质:保存和恢复内部状态. 英文:Memento 类型:行为型 2.类图及组成(白箱实现与黑箱实现) 前言:备忘录模式按照备忘录角色的形态不同,分为白箱实现与黑箱实现,两种模式与备忘录角色提供的接口模式有关: 由于备忘录角色构成不同,所以这里拆分成两种类图分别解释,对比一下,就能明白: 白箱实

设计模式——17.备忘录模式

备忘录模式(Memento) 在组件构建过程中,当某些对象的状态经常变化时,此时我们需要既对这些对象状态的变化进行管理又维持高层次模块的稳定性,即可以通过"状态变化"类的模式来进行解决. 典型的"状态变化"模式有: 状态模式(State) 备忘录模式(Memento) 备忘录模式(Memento)简介: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以将该对象恢复到原先保存的状态. 备忘录模式(Memento)结构: 备忘录

4 行为型模式之- 备忘录模式

备忘录模式介绍: 备忘录模式是一种行为模式,该模式用于保存对象当前的状态,并且在之后可以再次恢复到此状态,这有点像我们平时说的"后悔"药.备忘录模式实现的方式需要保证被保存的对象状态不能被对象从外界访问,目的是为了保护好被保存的这些对象状态的完整性以及内部实现不向外暴露 备忘录模式的定义: 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可以将对象恢复到原先的状态 对于备忘录模式来说,比较贴切的场景应该是游戏中的存档功能,该功能就是将游戏进度存储到

备忘录模式

备忘录模式,望文生义就知道它是用来做备忘的,或者可以直接说是“备份”.当需要保存当前状态,以便在不久要恢复此状态时,就可以使用“备忘录模式”.将当前”状态“备份,是不是又new一个类,然后将每个字段方法copy过去就可以了呢?或者说使用我们之前clone方法做深复制浅复制呢?其实不然,在<大话设计模式>中,作者提到了原因,这样会暴露更多的细节给客户端,不符合我们面向对象的思想.什么是暴露更多的细节给客户端?我们来看下面一段代码. 1 package day_27_memento; 2 3 /*

设计模式(12)---备忘录模式

备忘录模式   Memento (行为型模式) 1.概述 备忘录模式:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态. 例如:一些软件提供的撤销功能,游戏的存档读档功能. 2.结构图 3.代码 1 /* 2 * 原发器类 Originator 3 */ 4 public class Role { 5 6 private int level ; 7 private int life ; 8 9 public Role() { 10

C#设计模式(23)——备忘录模式(Memento Pattern)

一.引言 在上一篇博文分享了访问者模式,访问者模式的实现是把作用于某种数据结构上的操作封装到访问者中,使得操作和数据结构隔离.而今天要介绍的备忘者模式与命令模式有点相似,不同的是,命令模式保存的是发起人的具体命令(命令对应的是行为),而备忘录模式保存的是发起人的状态(而状态对应的数据结构,如属性).下面具体来看看备忘录模式. 二.备忘录模式介绍 2.1 备忘录模式的定义 从字面意思就可以明白,备忘录模式就是对某个类的状态进行保存下来,等到需要恢复的时候,可以从备忘录中进行恢复.生活中这样的例子经

设计模式之备忘录模式(Memento)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

大话设计模式_备忘录模式(Java代码)

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 简单描述:一个Memento类,代表Originator中要备份的属性.Originator负责生成备份和还原备份,CareTaker负责存储备份 大话设计模式中的截图: 例子代码: Memento类: 1 package com.longsheng.memento; 2 3 public class Memento { 4 5 private String sta