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

    2018-09-22 22:35:23

    备忘录模式

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

    备忘录模式UML类图

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

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

    Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或者检查。

    优缺点

    优点:

      1.提供了一种状态恢复机制,把要保存的细节封装在了Memento中,使用户能够方便的回到某个历史状态,如果需要更改保存的细节,也不会对客户端产生影响。

      2.实现了信息的封装,使用户不需要关心保存信息的细节。

    缺点:

      1.角色状态需要完整存储到备忘录对象中,如果状态数据很多很大,那么在资源消耗上,备忘录对象会非常消耗内存。

    适用场景:

      Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态,有时一些对象的内部信息必须保存在对象以外的地方,但是必须由对象自己读取,这是使用备忘录可以把复杂的对象内部信息对其它的对象屏蔽起来。作用是,当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

    代码示例

      (都是《大话设计模式》这本书的内容呀)背景:游戏进度备忘。假设我们需要保存的游戏角色的属性有:蓝量、血量、以及攻击力、防御力四个。

    1.Originator类。打游戏的时候只有角色自己拥有恢复存档和保存进度的能力

    #ifndef ORIGINATOR_H_
    #define ORIGINATOR_H_
    //这个类在本例中是游戏角色类
    //假设你正在玩某个游戏,回忆一下,具有存档和读取存档数据的是不是只有你的游戏角色呢?
    #include "Memento.h"
    #include <string>
    #include <iostream>
    
    class Originator
    {
    public:
        Memento createMemento()
        {
        return Memento(m_iLifeValues,m_iMP,m_iATK,m_iDef);    //创建一个备忘录,将当前需要保存的信息导入,并实例化出一个Memento对象
        }
        //从备忘录中恢复存档(为什么需要这个函数呢,你想一下,你在存档之后,下机了,下次再登录进入游戏,要恢复存档,数据必然要从某个地方读入,所以这个函数是必须的
        void restoreMemento(Memento objMemento)
        {
        m_iLifeValues = objMemento.getLifeValues();
            m_iMP = objMemento.getMP();
            m_iATK = objMemento.getATK();
            m_iDef = objMemento.getDef();
        }
        
        //显示属性值
        void show() const
        {
        std::cout << "Name: " << m_strRoleName << " LifeValues:" << m_iLifeValues << " MP:" << m_iMP << " ATK:" << m_iATK << " Def:" << m_iDef <<std::endl;
        }
        //设置属性的初始值
        void setInit(const int iLifeValues,const int iMP,const int iATK, const int iDef)  
        {
        m_iLifeValues = iLifeValues;
            m_iMP = iMP;
        m_iATK = iATK;
        m_iDef = iDef;
        }
        
        //和Boss玩玩,给你一下各项属性减去100(随便写的,所以结果可能出现负值)
        //返回值为false,则表示Game over
        bool beatAMonster()
        {
        m_iLifeValues -=100;
            m_iMP -= 100;
        m_iATK -=100;
        m_iDef -=100;
        if(0>= m_iLifeValues)
        {
            return false;
            }
        return true;
        }
        
        Originator(const std::string strRoleName) : m_strRoleName(strRoleName){};
        ~Originator() = default;
    private:
        //游戏角色的属性:生命值、魔法值、攻击力、防御力
        int m_iLifeValues{0};    //生命值
        int m_iMP{0};    //魔法值
        int m_iATK{0};    //攻击力
        int m_iDef{0};    //防御值
        std::string m_strRoleName;
    };
    #endif
    Originator

    2.Mementor类。备忘录,用于保存Originator类内部状态的外部类

    #ifndef MEMENTO_H_
    #define MEMENTO_H_
    //备忘录类,负责保存属性
    class Memento
    {
    public:
        //读取存档生命值
        int getLifeValues() const
        {
        return m_iLifeValues;
        }
        //读取魔法存档值
        int getMP() const
        {
        return m_iMP;
        }
        //读取攻击力存档
        int getATK() const
        {
        return m_iATK;
        }
        //读取防御力存档
        int getDef() const
        {
        return m_iDef;
        }
        Memento(const int iLifeValues,const int iMP,const int iATK,const int iDef):m_iLifeValues(iLifeValues),m_iMP(iMP),m_iATK(iATK),m_iDef(iDef){};
        Memento(const Memento& objMemento)
        {
        m_iLifeValues = objMemento.getLifeValues();
        m_iMP = objMemento.getMP();
        m_iATK = objMemento.getATK();
            m_iDef = objMemento.getDef();
        }
        Memento() = default;
        ~Memento() = default;
    private:
        int m_iLifeValues{0};    //生命值
        int m_iMP{0};    //魔法值
        int m_iATK{0};    //攻击力
        int m_iDef{0};    //防御力
    };
    #endif
    Memento

    3.Caretaker类。备忘录的管理类。

    #ifndef CARETAKER_H_
    #define CARETAKER_H_
    //管理者,这个类用来管理备忘录,它的作用,就是从加载备忘录的内容,将其恢复到某个对象
    
    #include "Memento.h"
    
    class Caretaker
    {
    public:
        //设置备忘录
        void setMemento(Memento objMemento)
        {
        m_Memento = objMemento;
        }
        Memento getMemento()
        {
        return m_Memento;
        }
    private:
        Memento m_Memento;        //持有一个备忘录对象,它是Caretaker进行备忘录管理的关键
    };
    #endif
    Caretaker

    4.client

    #include "Caretaker.h"
    #include "Originator.h"
    
    using namespace std;
    
    int main(int argc,char *argv[])
    {
        //创建一个游戏角色
        Originator objOriginator("ChongLou");
        //设置初始属性
        objOriginator.setInit(100,100,100,100);
        //保存初始状态
        Caretaker objCaretaker;
        objCaretaker.setMemento(objOriginator.createMemento());
        //显示初始状态
        objOriginator.show();
        //开始打怪
        objOriginator.beatAMonster();
        //显示打怪后的属性
        objOriginator.show();
        //加载存档
        objOriginator.restoreMemento(objCaretaker.getMemento());
        //显示加载存档后的属性
        objOriginator.show();
        return(1);
    }
    Client
  • 相关阅读:
    UOS怎么设置定时关机
    UOS如何修改源地址
    UOS如何进行全文搜索
    UOS如何查看硬盘序列号
    UOS如何修改右下角水印
    UOS怎么创建网页快捷方式
    应用商店安装软件提示uos-browser-stable错误,解决办法
    IHttpClientFactory Form 提交参数
    将.nuget文件夹移到其他盘
    windows docker 提示 bind: An attempt was made to access a socket
  • 原文地址:https://www.cnblogs.com/ToBeExpert/p/9691540.html
Copyright © 2011-2022 走看看