备忘录模式 (c++实现)

模式定义

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

模式动机

  • 备忘录模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,LieKong可以根据stateManager保存的BaseState信息换遇到前一状态。

UML类图

备忘录模式

源码实现

  • baseState.h
#ifndef BASESTATE_H
#define BASESTATE_H

#include <QObject>

class BaseState : public QObject
{
    Q_OBJECT
public:
    struct POSITION
    {
        int x;
        int y;
        int z;
    };
    explicit BaseState(QObject *parent = nullptr);
    explicit BaseState(POSITION pos, int xl, QObject *parent = nullptr);
    BaseState(const BaseState& state);
    BaseState& operator=(const BaseState& state);

    void SetPositon(POSITION pos);
    void SetXL(int xl);
    void PrintState();
signals:

public slots:

private:
    POSITION m_Position;//位置
    int     m_Xl;//血量
};

#endif // BASESTATE_H

  • baseState.cpp
#include <QDebug>
#include "basestate.h"

BaseState::BaseState(QObject *parent)
{

}

BaseState::BaseState(POSITION pos, int xl, QObject *parent)
: QObject(parent), m_Position(pos), m_Xl(xl)
{

}

BaseState::BaseState(const BaseState &state)
{
     if(this != &state)
    {
        this->m_Xl = state.m_Xl;
        this->m_Position.x = state.m_Position.x;
        this->m_Position.y = state.m_Position.y;
        this->m_Position.z = state.m_Position.z;
    }
}

BaseState &BaseState::operator=(const BaseState &state)
{
    if(this != &state)
    {
        this->m_Xl = state.m_Xl;
        this->m_Position.x = state.m_Position.x;
        this->m_Position.y = state.m_Position.y;
        this->m_Position.z = state.m_Position.z;
    }
    return *this;
}

void BaseState::SetPositon(POSITION pos)
{
    m_Position.x = pos.x;
    m_Position.y = pos.y;
    m_Position.z = pos.z;
}

void BaseState::SetXL(int xl)
{
    m_Xl = xl;
}

void BaseState::PrintState()
{
        qDebug() << QString("现在的坐标是:x = %1, y = %2, z = %3;").arg(m_Position.x).arg(m_Position.y).arg(m_Position.z);
        qDebug() << QString("现在的血量是:%1").arg(m_Xl);
        qDebug() << endl;
}

  • liekong.h
#ifndef LIEKONG_H
#define LIEKONG_H

#include <QObject>
#include <functional>
#include "basestate.h"

using skill1 = std::function<bool (int)>;
using skill2 = std::function<void(void)>;
using skill3 = std::function<void(void)>;

class Liekong : public QObject
{
    Q_OBJECT
public:
    explicit Liekong(QObject *parent = nullptr);
    BaseState State();
    void SetState(BaseState state);

    void UnleashSkills(const skill1& skill);//释放时光倒回技能
    void ChangeState();//改变状态
private:
    BaseState CreateState();

signals:

public slots:
private:
    BaseState m_State;
};

#endif // LIEKONG_H

  • liekong.cpp
#include <QDebug>
#include "liekong.h"

Liekong::Liekong(QObject *parent) : QObject(parent)
{
    CreateState();
}

BaseState Liekong::State()
{
    m_State.PrintState();
    return m_State;
}

void Liekong::SetState(BaseState state)
{
    m_State= state;
}

BaseState Liekong::CreateState()
{
    BaseState::POSITION pos;
    pos.x = 20;
    pos.y = 50;
    pos.z = 67;
    m_State = BaseState(pos, 100);
    return m_State;
}

void Liekong::UnleashSkills(const skill1& skill)
{
    int a = 0;
    skill(a);
}

void Liekong::ChangeState()
{
    BaseState::POSITION pos;
    pos.x = 10;
    pos.y = 10;
    pos.z = 10;
    m_State.SetPositon(pos);
    m_State.SetXL(10);
}

  • statemanager.h
#ifndef STATEMANAGER_H
#define STATEMANAGER_H

#include <QObject>
#include "basestate.h"

class StateManager : public QObject
{
    Q_OBJECT
public:
    explicit StateManager(QObject *parent = nullptr);

    void SetState(const BaseState& state);
    BaseState State();

signals:
public slots:

private:
    BaseState m_State;
};

#endif // STATEMANAGER_H

  • satemanager.cpp
#include "statemanager.h"

StateManager::StateManager(QObject *parent) : QObject(parent)
{

}

void StateManager::SetState(const BaseState& state)
{
    m_State = state;
}

BaseState StateManager::State()
{
    return m_State;
}

  • main.cpp
/************************************
    * @brief	:  需要三个类,我们以 守望先锋 里的裂空的一个回到去过去的技能为背景写一个实现
    * @author	:   wzx
    * @date	:   2020-04-30
    * @project	:  Memento
*************************************/
#include <QCoreApplication>
#include <QDebug>
#include "liekong.h"
#include "statemanager.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    Liekong lk;
    qDebug() << "初始状态:";
    BaseState state = lk.State();
    
    StateManager manage;
    manage.SetState(state);
    
    lk.ChangeState();
    qDebug() << "更新后状态:";
    lk.State();
    
    BaseState state1 = manage.State();
    
    lk.UnleashSkills([&lk, state1](int a){
        lk.SetState(state1);
        qDebug() << "param = " << a;
        return true;
    });
    qDebug() << "还原后状态:";
    lk.State();
    
    return a.exec();
}

  • 运行结果

初始状态:

“现在的坐标是:x = 20, y = 50, z = 67;”

“现在的血量是:100”

更新后状态:

“现在的坐标是:x = 10, y = 10, z = 10;”

“现在的血量是:10”

还原后状态:

“现在的坐标是:x = 20, y = 50, z = 67;”

“现在的血量是:100”

优点

  • 封装细节,如果要更改保存的细节,也不会影响到客户端

缺点