狀態模式
當一個對象的內在狀態改變時允許改變其行爲,這個對象看起來像是改變了其類。
狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把複雜的判斷邏輯簡化。
狀態模式的優點:將與特定狀態相關的行爲局部化,並且將不同狀態的行爲分割開來。
抽象狀態類:定義一個接口封裝 與context的一個狀態相關的 行爲
這個狀態是Context中的私有屬性
狀態模式就是通過把各種狀態的邏輯轉移到state的各個子類中,減少相互依賴。
這樣做可以消除龐大的條件分支語句
以COC中的兵營爲例
當建造的時候只有土地和護欄;當升級的時候會影響造兵速度;當兵滿的時候會顯示兵營已滿;當正在訓練的時候會有訓練兵的特效。
state.h
#ifndef DESIGN_PATTERN_STATE_H
#define DESIGN_PATTERN_STATE_H
#include<iostream>
#include"Barrack.h"
using std::cout;
using std::endl;
class Barrack;
class barrack_state{
public:
virtual void show(Barrack* barrack);
};
class barrack_building : public barrack_state {//公有繼承
public:
void show(Barrack* barrack) override ;
};
class barrack_upgrading :public barrack_state {
public:
void show(Barrack* barrack) override ;
};
class barrack_full :public barrack_state {
public:
void show(Barrack* barrack) override ;
};
class barrack_training :public barrack_state {
public:
void show(Barrack* barrack) override ;
};
#endif //DESIGN_PATTERN_STATE_H
state.cpp
#include "State.h"
void barrack_building::show(Barrack* barrack)
{
if(barrack->statetype=="building")
cout << "building and fence" << endl;
}
void barrack_upgrading::show(Barrack* barrack)
{
if(barrack->statetype=="upgrading")
cout << "upgrading" << endl;
}
void barrack_state::show(Barrack* barrack)
{
}
void barrack_full::show(Barrack* barrack)
{
if (barrack->statetype=="full")
{
cout << "full" << endl;
}
}
void barrack_training::show(Barrack* barrack)
{
if(barrack->statetype=="training")
cout << "trainging" << endl;
}
Barrack.h
#ifndef DESIGN_PATTERN_BARRACK_H
#define DESIGN_PATTERN_BARRACK_H
#include<string>
#include"State.h"
using std::string;
class barrack_state;
class Barrack{
public:
Barrack();
void show();
void upgrading();
void trainging();
void full();
string statetype;
private:
barrack_state* state;
};
#endif //DESIGN_PATTERN_BARRACK_H
Barrack.cpp
#include "Barrack.h"
Barrack::Barrack()
{
statetype = "building";
this->state = new barrack_building();//只有公有繼承才能轉換爲基類
}
void Barrack::show()
{
this->state->show(this);
}
void Barrack::upgrading()
{
statetype = "upgrading";
state = new barrack_upgrading();
}
void Barrack::trainging()
{
statetype = "training";
state = new barrack_training();
}
void Barrack::full()
{
statetype = "full";
state = new barrack_full();
}
頭文件互相包含問題
在自己寫狀態模式的過程中,發現出現類名未聲明的情況,百思不得其解,不斷調試未果。靈光乍現,懷疑是頭文件互相包含導致的問題,遂查資料找到問題並解決。
不可避免的存在頭文件互相包含的情況。
涉及到C/C++編譯原理,與參考資料中的情況略微不同,其func中會使用Class A,而在Class A中沒有func,從而只需要在func之前加上Class A的聲明即可正確運行。
而狀態模式的使用中,Context類的聲明中會有State類,State類的聲明中會有Context類,所以需要在分別在各自前方聲明另一個類。如上述代碼所示。