2、智能空調的設計與實現
某軟件公司將開發一套智能空調系統: 系統檢測到溫度處於20---30度之間,則切換到常溫狀態;溫度處於30---45度,則切換到制冷狀態; 溫度小於20度,則切換到制熱狀態。請使用狀態模式對此系統進行設計。
從需求中可以看出,空調可以處於三種狀態: 制熱狀態、常溫狀態、制冷狀態。每種狀態下都存在三種行為:保持常溫、制冷、制熱。
空調抽象狀態實現代碼如下:
//空調抽象狀態類
class AirConditionerState
{
public:
//保持常溫
virtual void KeepNormalTemperature(AirConditioner * pAirConditioner) = 0;
//制冷
virtual void refrigerate(AirConditioner * pAirConditioner) = 0;
//制熱
virtual void Heat(AirConditioner * pAirConditioner) = 0;
}; 三種具體狀態類聲明如下://常溫狀態
class NormalTemperatureState : public AirConditionerState
{
public:
//保持常溫
void KeepNormalTemperature(AirConditioner * pAirConditioner);
//制冷
void refrigerate(AirConditioner * pAirConditioner);
//制熱
void Heat(AirConditioner * pAirConditioner);
};
//制冷狀態
class RefrigerateState : public AirConditionerState
{
public:
//保持常溫
void KeepNormalTemperature(AirConditioner * pAirConditioner);
//制冷
void refrigerate(AirConditioner * pAirConditioner);
//制熱
void Heat(AirConditioner * pAirConditioner);
};
//制熱狀態
class HeatState : public AirConditionerState
{
public:
//保持常溫
void KeepNormalTemperature(AirConditioner * pAirConditioner);
//制冷
void refrigerate(AirConditioner * pAirConditioner);
//制熱
void Heat(AirConditioner * pAirConditioner);
}; 每種狀態下都存在保持常溫、制冷、制熱方法。這些方法帶有一個AirConditioner類參數,方法內部使用這個參數回調空調的溫度值,根據這個溫度值,用於判斷該方法如何實現,以及如何切換到其他狀態。三種狀態實現代碼如下:/******************************正常溫度狀態******************************************/
//保持常溫
void NormalTemperatureState::KeepNormalTemperature(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature > 20 && nTemperature <= 30 )
{
cout << "已經是常溫狀態,不能調節為常溫" << endl;
}
}
//制冷
void NormalTemperatureState::refrigerate(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature > 30 && nTemperature <= 45 )
{
pAirConditioner->SetAirConditionerState(pAirConditioner->GetRefrigerateState());
cout << "切換到制冷狀態" << endl;
}
}
//制熱
void NormalTemperatureState::Heat(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature <= 20 )
{
pAirConditioner->SetAirConditionerState(pAirConditioner->GetHeatState());
cout << "切換到制熱狀態" << endl;
}
}
/******************************制冷狀態******************************************/
//保持常溫
void RefrigerateState::KeepNormalTemperature(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature > 20 && nTemperature <= 30 )
{
pAirConditioner->SetAirConditionerState(pAirConditioner->GetNormalTemperatureState());
cout << "切換到常溫狀態" << endl;
}
}
//制冷
void RefrigerateState::refrigerate(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature > 30 && nTemperature <= 45 )
{
cout << "已經是制冷狀態,不能調節為制冷狀態" << endl;
}
}
//制熱
void RefrigerateState::Heat(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature <= 20 )
{
pAirConditioner->SetAirConditionerState(pAirConditioner->GetHeatState());
cout << "切換到制熱狀態" << endl;
}
}
/******************************制熱狀態******************************************/
//保持常溫
void HeatState::KeepNormalTemperature(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature > 20 && nTemperature <= 30 )
{
pAirConditioner->SetAirConditionerState(pAirConditioner->GetNormalTemperatureState());
cout << "切換到常溫狀態" << endl;
}
}
//制冷
void HeatState::refrigerate(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature > 30 && nTemperature <= 45 )
{
pAirConditioner->SetAirConditionerState(pAirConditioner->GetRefrigerateState());
cout << "切換到制冷狀態" << endl;
}
}
//制熱
void HeatState::Heat(AirConditioner * pAirConditioner)
{
int nTemperature = pAirConditioner->GetTemperature();
if( nTemperature <= 20 )
{
cout << "已經是制熱狀態,不能調節為制熱狀態" << endl;
}
}
空調類,也就是環境類Contex,維護了一個狀態的引用,實現的時候將調用狀態對象的方法。聲明代碼如下://空調類
class AirConditioner
{
private:
//空調名稱
string m_strAirName;
//空調當前溫度
int m_nTemperature;
//常溫狀態
AirConditionerState * m_pNormalTemperatureState;
//制冷狀態
AirConditionerState * m_pRefrigerateState;
//制熱狀態
AirConditionerState * m_pHeatState;
//當前溫度狀態
AirConditionerState * m_pCurState;
public:
//構造函數
AirConditioner(string strAirName, int nTemperature);
//虛構函數
~AirConditioner();
//調節溫度
void SetTemperature(int nTemperature);
//獲取溫度
int GetTemperature();
//設置空調狀態
void SetAirConditionerState(AirConditionerState * pAirConditionerState);
//獲取常溫狀態
AirConditionerState * GetNormalTemperatureState();
//獲取制冷狀態
AirConditionerState * GetRefrigerateState();
//獲取制熱狀態
AirConditionerState * GetHeatState();
//保持常溫
void KeepNormalTemperature();
//制冷
void refrigerate();
//制熱
void Heat();
};
空調類實現代碼如下://構造函數
AirConditioner::AirConditioner(string strAirName, int nTemperature)
{
m_strAirName = strAirName;
m_nTemperature = nTemperature;
m_pNormalTemperatureState = new NormalTemperatureState();
m_pRefrigerateState = new RefrigerateState();
m_pHeatState = new HeatState();
m_pCurState = m_pNormalTemperatureState;
}
//虛構函數
AirConditioner::~AirConditioner()
{
delete m_pNormalTemperatureState;
m_pNormalTemperatureState = NULL;
delete m_pRefrigerateState;
m_pRefrigerateState = NULL;
delete m_pHeatState;
m_pHeatState = NULL;
}
//調節溫度
void AirConditioner::SetTemperature(int nTemperature)
{
m_nTemperature = nTemperature;
}
//獲取溫度
int AirConditioner::GetTemperature()
{
return m_nTemperature;
}
//設置空調狀態
void AirConditioner::SetAirConditionerState(AirConditionerState * pAirConditionerState)
{
m_pCurState = pAirConditionerState;
}
//獲取常溫狀態
AirConditionerState * AirConditioner::GetNormalTemperatureState()
{
return m_pNormalTemperatureState;
}
//獲取制冷狀態
AirConditionerState * AirConditioner::GetRefrigerateState()
{
return m_pRefrigerateState;
}
//獲取制熱狀態
AirConditionerState * AirConditioner::GetHeatState()
{
return m_pHeatState;
}
//保持常溫
void AirConditioner::KeepNormalTemperature()
{
m_pCurState->KeepNormalTemperature(this);
}
//制冷
void AirConditioner::refrigerate()
{
m_pCurState->refrigerate(this);
}
//制熱
void AirConditioner::Heat()
{
m_pCurState->Heat(this);
}
測試代碼實現如下:#include編譯並執行,結果如下:#include "AirConditioner.h" using namespace std; int main() { AirConditioner * pAirConditioner = new AirConditioner("海爾空調", 25); /****************常溫狀態*************************/ pAirConditioner->KeepNormalTemperature(); cout << endl; /****************制冷狀態*************************/ pAirConditioner->SetTemperature(33); pAirConditioner->refrigerate(); cout << endl; /****************制熱狀態*************************/ pAirConditioner->SetTemperature(15); pAirConditioner->Heat(); /****************銷毀操作*************************/ delete pAirConditioner; pAirConditioner = NULL; return 0; }

將具體行為封裝在常溫狀態、制冷狀態、制熱狀態中。空調類(也就是環境類)維持一個當前狀態的引用,當客戶端調用環境類的方法時,將該調用操作委托給具體狀態類。具體狀態類實現該狀態下的行為,以及控制切換到其他狀態。客戶端無需直接操作具體的狀態類,而是由環境類代為處理,降低了客戶端與具體狀態類的耦合性。如果需要添加具體的狀態類也很容易,只需要繼承於抽象狀態類並對環境類稍加修改就可以了。另外,也避免了大量if...else臃腫語句,把這些條件判斷都封裝成一個個狀態類。