zoukankan      html  css  js  c++  java
  • 设计模式之备忘录模式

    生活中大家可能都幻 想过如果当初我没怎么样怎么样就好了,当产生这样的想法的时候一定是发生什么不如意的事。生活是现实的,时间也永远不会回到做错事之前的一刹那。软件虽服 务于生活,模拟生活却也和生活有所不同,应用软件时,我们可以比较容易的进行备忘,比如编辑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类内部的细节,并且要完 成的操作也很多,这时如果游戏角色加入一些要保存的属性更改起来也不方便。想想备忘录模式的好处吧~~~

  • 相关阅读:
    解决原子性问题?脑海中有这个模型就可以了
    基础面试,为什么面试官总喜欢问String?
    学并发编程,透彻理解这三个核心是关键
    Spring Boot 统一异常这样处理和剖析,安否?
    每天用SpringBoot,还不懂RESTful API返回统一数据格式是怎么实现的?
    Java网络编程的Java流介绍
    Java设计模式学习记录-模板方法模式
    Java网络编程的基本网络概念
    Java设计模式学习记录-状态模式
    Java设计模式学习记录-观察者模式
  • 原文地址:https://www.cnblogs.com/kexb/p/3676359.html
Copyright © 2011-2022 走看看