一、UML圖
二、概念
狀態模式(State):當一個對象的內在狀態改變時允許改變其行爲,這個對象看起來像是改變了其類。
三、說明
下面是來自書本和網絡的對狀態模式的定義和分析:
(1)狀態模式允許對象在內部狀態改變時改變它的行爲,對象看起來好像修改了它的類。看起來,狀態模式好像是神通廣大很厲害似的——居然能夠“修改自身的類”!
(2)適用場景:
a)狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把複雜的判 斷邏輯簡單化。(簡單來說,就是把各種if else 轉變成了一個個的具體狀態,原來if else 每種情況下的操作現在轉換到了某個具體狀態中)
b)當一個對象行爲取決於它的狀態,並且它必須在運行時刻根據狀態改變它的行爲時,就可以考慮使用狀態模式了。
四、角色
(1)Context類:在該類內部維護一個ConcreteState子類的一個實例,這個實例定義當前的狀態。
(2)State類:抽象狀態類,定義一個 接口以封裝與Context的一個特定狀態相關的行爲。
(3)ConcreteStateA,ConcreteStateB類:具體狀態類,每一個子 類實現一個與Context的一個狀態相關的行爲。
五、C++實現
(1)State.h(抽象狀態類和具體狀態類的聲明和定義都在State.h和State.cpp中)
#ifndef STATE
#define STATE
//#include "Work.h"
extern class Work;
class State
{
public:
State(){};
virtual void writeProgram(Work* w){};
};
class ForenoonState:public State
{
public:
void writeProgram(Work* w);
};
class NoonState:public State
{
public:
void writeProgram(Work* w);
};
class AfternoonState:public State
{
public:
void writeProgram(Work* w);
};
class EveningState:public State
{
public:
void writeProgram(Work* w);
};
class SleepingState:public State
{
public:
void writeProgram(Work* w);
};
class RestState:public State
{
public:
void writeProgram(Work* w);
};
#endif
(2)State.cpp
#include <iostream>
#include "State.h"
#include "Work.h"
using namespace std;
void ForenoonState::writeProgram(Work* w)
{
if(w->getHour()<12)
{
cout<<"當前時間:"<<w->getHour()<<"點 "<<"上午工作,精神百倍"<<endl;
}
else
{
w->setState(new NoonState);
w->writeProgram();
}
}
void NoonState::writeProgram(Work* w)
{
if(w->getHour()<13)
{
cout<<"當前時間:"<<w->getHour()<<"點 "<<"餓了,午飯;犯困,午休"<<endl;
}
else
{
w->setState(new AfternoonState);
w->writeProgram();
}
}
void AfternoonState::writeProgram(Work* w)
{
if(w->getHour()<17)
cout<<"當前時間:"<<w->getHour()<<"點 "<<"下午狀態還不錯,繼續努力"<<endl;
else
{
w->setState(new EveningState);
w->writeProgram();
}
}
void EveningState::writeProgram(Work* w)
{
if(w->getFinish())
{
w->setState(new RestState);
w->writeProgram();
}
else
{
if(w->getHour()<21)
cout<<"當前時間:"<<w->getHour()<<"點 "<<"加班哦,疲憊至極"<<endl;
else
{
w->setState(new SleepingState);
w->writeProgram();
}
}
}
void SleepingState::writeProgram(Work* w)
{
cout<<"當前時間:"<<w->getHour()<<"點 "<<"不行了,睡着了"<<endl;
}
void RestState::writeProgram(Work* w)
{
cout<<"當前時間:"<<w->getHour()<<"點 "<<"下班回家了"<<endl;
}
(3)Work.h(這裏的Work就是狀態模式中的Context)
#ifndef WORK
#define WORK
#include "State.h"
class Work
{
private:
State* current;
double Hour;
bool finish;
public:
Work();
~Work();
double getHour();
void setHour(double HOUR);
bool getFinish();
void setFinish(bool FINISH);
void setState(State* s);
void writeProgram();
};
#endif
(4)Work.cpp
#include "Work.h"
Work::Work()
{
current=new ForenoonState;
Hour=9;
finish=false;
}
Work::~Work()
{
if(current!=0)
delete current;
}
double Work::getHour()
{
return Hour;
}
void Work::setHour(double HOUR)
{
Hour=HOUR;
}
bool Work::getFinish()
{
return finish;
}
void Work::setFinish(bool FINISH)
{
finish=FINISH;
}
void Work::setState(State* s)
{
if(current!=0)
delete current;
current=s;
}
void Work::writeProgram()
{
current->writeProgram(this);
}
(5)main.cpp(客戶端)
#include <iostream>
#include <cstdlib>
#include "Work.h"
//#include "State.h"
using namespace std;
void main()
{
Work emergencyProjects;
emergencyProjects.setHour(9);
emergencyProjects.writeProgram();
emergencyProjects.setHour(10);
emergencyProjects.writeProgram();
emergencyProjects.setHour(12);
emergencyProjects.writeProgram();
emergencyProjects.setHour(13);
emergencyProjects.writeProgram();
emergencyProjects.setHour(14);
emergencyProjects.writeProgram();
emergencyProjects.setHour(17);
emergencyProjects.writeProgram();
emergencyProjects.setFinish(false);
emergencyProjects.setHour(19);
emergencyProjects.writeProgram();
emergencyProjects.setHour(22);
emergencyProjects.writeProgram();
system("pause");
}
注意:上面的代碼會出現兩個類相互調用的情況,請查看日誌:C++中兩個類互相引用的解決方法
(6)運行截圖