備忘錄模式 (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”
優點
- 封裝細節,如果要更改保存的細節,也不會影響到客戶端