设计模式学习(十三) 备忘录模式

本文通过游戏主角状态保存与恢复的实例,详细介绍了备忘录模式的原理与应用。使用C++实现角色状态的备份与恢复,避免了Clone方法的安全隐患,确保数据安全。


这是个人学习编程模式的系列学习笔记第十三篇。
采用Qt Creator进行编写,但尽量采用C++基础语法。
备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
比较典型的应用是过程中需要根据保存的数据,恢复之前的运行环境。比如游戏运行过程中保存当前进度,在需要的时候重新加载(比如打大Boss死掉了)。也可以是在做文本编辑时,撤销当前操作。
使用备忘录模式进行备份而不是使用Clone方法备份,主要有几个原因:
1、需要备份的东西并不是对象的全部
2、如果Clone,会形成一个新的对象,具有同样的行为(方法),不利于数据安全
3、不希望暴露备份对象的实现细节

场景描述

假设有一个简单的游戏,游戏主角有3个属性:血、金钱、战力。主角有多个行为。保存状态时保存主角的这三个状态。在需要恢复的时候,从保存的状态中重新加载主角状态恢复到之前状态。

设计思路

游戏主角类:三个属性(血、金钱、战力),四个行为(战斗、花钱、保存状态、重载状态)。
状态存储类:三个属性,血、金钱和战力。
状态管理类:负责状态对象的管理,不能接触具体的状态存储等细节。

UML

在这里插入图片描述

代码

#include <iostream>
using namespace std;

class Status
{
public:
    int m_blood;
    int m_money;
    int m_force;
public:
    Status(int blood, int money, int force):m_blood(blood),m_money(money),m_force(force) {}
};

class Role
{
private:
    int m_blood;
    int m_money;
    int m_force;
public:
    Role(int blood, int money, int force):m_blood(blood),m_money(money),m_force(force) {}
    void buy() {if(m_money > 0) m_money--;}
    void attack() {if(m_blood > 0) {m_blood--; m_force++;}}
    void displayStatus()
    {
        cout<<"Blood: "<<m_blood<<"\n";
        cout<<"Money: "<<m_money<<"\n";
        cout<<"Force: "<<m_force<<"\n";
    }
    Status* saveStatus()
    {
       return new Status(m_blood, m_money, m_force);
    }
    bool reload(Status* status)
    {
        m_blood = status->m_blood;
        m_money = status->m_money;
        m_force = status->m_force;
        return true;
    }
};

class StatusCaretaker
{
private:
    Status* m_status = 0;
public:
    void setStatus(Status* status) {m_status = status;}
    Status* getStatus() {return m_status;}

    ~StatusCaretaker() {delete m_status;}
};

int main()
{
    Role* role = new Role(10, 20, 30);
    StatusCaretaker* caretaker = new StatusCaretaker();
    cout<<"The role\'s status: \n";
    cout<<"Initial status:\n";
    role->displayStatus();
    caretaker->setStatus(role->saveStatus());
    role->buy();
    role->attack();
    cout<<"After buy and attack:\n";
    role->displayStatus();
    role->reload(caretaker->getStatus());
    cout<<"Reload status:\n";
    role->displayStatus();
    delete caretaker;
    delete role;
    return 0;
}

运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值