狀態模式
模式定義
狀態模式(state),當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了其類。
模式動機
- 狀態模式主要解決的是當控制一個物件狀態轉換的條件表示式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把複雜的判斷邏輯簡化。
- 當一個物件的行為取決於它的狀態,並且它必須在執行時根據狀態改變它的行為時,就可以考慮使用狀態模式了。
UML類圖
原始碼實現
- state.h
#include <string>
class People;
class State
{
public:
State(std::string context);
virtual ~State();
virtual void Handle(People* people) = 0;
std::string Content();
protected:
std::string m_Content;
private:
int m_Time;
};
- people.h
#include "state.h"
class People
{
public:
People(State* state);
void ChangeState(State* state);
void Show();
void SetTime(int time);
int Time();
private:
int m_Now;
State* m_State;
};
- people.cpp
#include <iostream>
#include "people.h"
People::People(State* state)
:m_State(state)
{
}
void People::ChangeState(State* state)
{
m_State = state;
}
void People::Show()
{
std::cout << "來吧,展示!" << std::endl;
std::cout << "當前狀態:" << m_State->Content() << std::endl;
}
void People::SetTime(int time)
{
m_Now = time;
m_State->Handle(this);
}
int People::Time()
{
return m_Now;
}
- lifestate.h
#include "state.h"
class LifeState : public State
{
public:
LifeState(std::string content = "生活狀態");
void Handle(People *people) override;
};
- lifestate.cpp
#include "lifestate.h"
#include "workstate.h"
#include "people.h"
LifeState::LifeState(std::string content)
:State(content)
{
}
void LifeState::Handle(People *people)
{
int time = people->Time();
if(time > 9 && time < 18)
people->ChangeState(new WorkState());
}
- main.cpp
#include <iostream>
#include <memory>
#include "people.h"
#include "workstate.h"
#include "playstate.h"
#include "lifestate.h"
using namespace std;
int main()
{
std::shared_ptr<State> state1 = std::make_shared<WorkState>();
People p(state1.get());
p.Show();
p.SetTime(9);
p.Show();
p.SetTime(11);
p.Show();
p.SetTime(13);
p.Show();
p.SetTime(20);
p.Show();
p.SetTime(22);
p.Show();
return 0;
}
- 執行結果
來吧,展示!
當前狀態:工作狀態
來吧,展示!
當前狀態:工作狀態
來吧,展示!
當前狀態:工作狀態
來吧,展示!
當前狀態:玩兒樂狀態
來吧,展示!
當前狀態:生活狀態
優點
模式的優點
-
將與特定狀態相關的行為區域性化,並且將不同狀態的行為分割開來。
將特定的狀態相關的行為都放入一個物件中,由於所有與狀態相關的程式碼都存在於某個ConcreteState中,所以通過定義新的子類可以很容易的增加新的狀態和轉換。
-
消除龐大的條件分支語句。
-
狀態模式通過把各種狀態轉移邏輯分佈到state的子類之間,來減少相互之間的依賴。
缺點
模式的缺點
- 每個子狀態跳轉到另外一個子狀態是固定的,不能夠靈活設定下一個狀態,也就是說狀態之間裝換最好是一對一的,否則就又會出現一個龐大的分支語句。從這點上來看還有點像職責鏈模式。