1. 程式人生 > >C++設計模式之狀態模式(二)

C++設計模式之狀態模式(二)

virtual alt 虛構函數 需求 rate names clas term delete

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 <iostream>
#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;
}
編譯並運行,結果例如以下:

技術分享
將詳細行為封裝在常溫狀態、制冷狀態、制熱狀態中。

空調類(也就是環境類)維持一個當前狀態的引用,當client調用環境類的方法時,將該調用操作托付給詳細狀態類。詳細狀態類實現該狀態下的行為,以及控制切換到其它狀態。client無需直接操作詳細的狀態類,而是由環境類代為處理。減少了client與詳細狀態類的耦合性。假設須要加入詳細的狀態類也非常easy,僅僅須要繼承於抽象狀態類並對環境類稍加改動就能夠了。另外。也避免了大量if...else臃腫語句。把這些條件推斷都封裝成一個個狀態類。






C++設計模式之狀態模式(二)