设计模式之备忘录模式

生活中大家可能都幻 想过如果当初我没怎么样怎么样就好了,当产生这样的想法的时候一定是发生什么不如意的事。生活是现实的,时间也永远不会回到做错事之前的一刹那。软件虽服 务于生活,模拟生活却也和生活有所不同,应用软件时,我们可以比较容易的进行备忘,比如编辑word或者txt时,我们使用的快捷键ctrl+z。还有我 们可能也对系统进行过备份吧~~~

1.初识备忘录模式

实际上在软件中备忘录模式的使用时非常频繁的,并且备忘录模式又是比较简单的一种 设计模式,所以可以说是性价比很高。比如我们玩中国象棋的时候需要悔棋,浏览网页时需要后退等等这些都是备忘录模式的应用。但在这里我们想说的是关于游戏 进度保存的问题。当我们玩一款单机游戏的时候,可能我们突然有什么事要关机出去一段时间,或者好不容打到关底了,但是boss打不过还要重玩,这是我们可 能也希望在打最终boss之前保存一下,这些时候可能我们都希望使用备忘录模式,利用备忘录模式保存打boss之前的状态,如果打boss不过呢,还可以 恢复进度,从打boss之前的状态开始重打~~~

Gof对备忘录模式是这样说的:

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

同样的我们还看看备忘录模式的结构图:

从结构中看出备忘录模式包含3个角色:

1.Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。

2.Memento(备忘录):负责存储Originator对象的内部状态,并 可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。 Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。

3.Caretaker(管理者):负责备忘录Memento,不能对Memento的内容进行访问或者操作。

 
2.实现备忘录模式

现在假设游戏角色中有两个属性,角色名称和角色生命值,现在要进行的保存游戏角色的生命值,但是游戏角色名称不用保存。我们来看看怎样利用备忘录模式的代码实现:

复制代码
 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 //角色备忘录类
 7 class RoleStateMemento
 8 {
 9 private:
10     int vitality;
11 public:
12     RoleStateMemento(){};
13     RoleStateMemento(int vit)
14     {
15         this->vitality = vit;
16     }
17     int get_vitality()
18     {
19         return vitality;
20     }
21 };
22 
23 //游戏角色类
24 class GameRole
25 {
26 private:
27     int vitality;
28     string name;
29 public:
30     GameRole(int Vit,string Name)
31     {
32         this->vitality = Vit;
33         this->name = Name;
34     }
35     //保存进度,只保存了生命力(vitality)
36     RoleStateMemento save_state()
37     {
38         RoleStateMemento memento(vitality);
39         return memento;
40     }
41     //恢复进度
42     void role_state_recover(RoleStateMemento memento)
43     {
44         this->vitality = memento.get_vitality();
45     }
46     //展示游戏角色状态
47     void show()
48     {
49         cout<<"游戏角色名称: "<<name<<endl;
50         cout<<"游戏角色生命值: "<<vitality<<endl;
51     }
52     //大战boss生命值变为0
53     void fight()
54     {
55         this->vitality = 0;
56     }
57 };
58 //角色状态管理者类
59 class RoleStateCaretaker
60 {
61 private:
62     RoleStateMemento memento;
63 public:
64     void set_memento(RoleStateMemento mem)
65     {
66         this->memento = mem;
67     }
68     RoleStateMemento get_memento()
69     {
70         return this->memento;
71     }
72 };
73 
74 int main()
75 {
76     //大战boss前
77     GameRole Vincent(100,"VincentChen");
78     Vincent.show();
79     //保存进度
80     RoleStateCaretaker StateManager;
81     StateManager.set_memento(Vincent.save_state());
82     //大战boss
83     Vincent.fight();
84     cout<<endl<<"大战boss后的状态:"<<endl;
85     Vincent.show();
86     //恢复进度
87     Vincent.role_state_recover(StateManager.get_memento());
88     cout<<endl<<"恢复进度后的状态:"<<endl;
89     Vincent.show();
90     return 0;
91 }
复制代码

 运行结果:

小结:想 一想如果不用备忘录模式怎么实现呢?如果要保存进度就要在main函数(客户端)中保存Vincent的vitality属性的值,然后恢复进度就要将 Vincent的citality属性赋值为已经保存下来的那个值,这样一来的话,main函数(客户端)要知道GameRole类内部的细节,并且要完 成的操作也很多,这时如果游戏角色加入一些要保存的属性更改起来也不方便。想想备忘录模式的好处吧~~~

原文地址:https://www.cnblogs.com/kexb/p/3676359.html