狀態模式(State)-設計模式(九)

1、作用

允許一個對象在其內部狀態改變時改變它的行爲。

每個人、事物在不同的狀態下會有不同的表現,而一個狀態在不同的表現下會轉換爲另一個狀態。

舉個例子:
我們去買一杯奶茶,有熱飲、冷飲、和常溫三種可供選擇,我們首先選擇了常溫的,在奶茶開始製作的時,擡頭看了看天氣,現在烈日炎炎,想想一杯冰涼的奶茶是不是能夠按下躁動的心,因此立馬決定告訴店員,我需要改成冷飲,而店員呢,也就需要改變奶茶的製作流程。

2、解決的問題

我們在搬磚中經常會遇到幾種狀態的選擇,比如簡單的鼠標的三種狀態,遇到這種情況時,通常的方式是使用switch-case語句實現,這種實現方式簡單粗暴,很香。但是,如果有十幾種狀態,甚至幾十種呢,如果還是像往常一樣寫switch-case語句,維護一大組這樣的語句是異常困難並且很容易出錯的。就算強悍的我們維護了這樣一大組的switch-case,後續如果有新增加的狀態和行爲,就需要對這段代碼重新改造增加,擴展性和維護會變得很差。

狀態模式的出現很好的解決了這種情況,我們有很多的狀態,每一個狀態實現一個行爲,狀態改變時,對應的行爲也就會跟着改變,這樣我們在整個代碼中就維護了一個狀態。

#include<iostream>
using namespace std;

class Context;
class State
{
public:
	virtual ~State(){}
	virtual void Handle(Context *pContext)=0;
};
class Context
{
	public:
	Context(State* pState):m_pState(pState){}
	~Context()
	{
		delete m_pState;
		m_pState = NULL;
	}
	
	void Request()
	{
		if(NULL != m_pState)
		m_pState->Handle(this);
	}
	
	void ChangeState(State* pState)
	{
		if(NULL != m_pState)
		{
			delete m_pState;
			m_pState = NULL;
		}
		m_pState = pState;
	}
private:
	State *m_pState;
};

class HotDrinks : public State
{
public:
	void Handle(Context* pContext);
};


class ColdDrinks : public State
{
public:
	void Handle(Context* pContext);
};

void HotDrinks::Handle(Context* pContext)
{
	cout << "Make a hot drink ..." << endl;
	
	if(NULL != pContext)	//突然改變 需要 冷飲 
	{
		pContext->ChangeState(new ColdDrinks());
	}
}
void ColdDrinks::Handle(Context* pContext)
{
	cout << "Make a cold drink ..." << endl;
	if(NULL!=pContext)
	{
		pContext->ChangeState(new HotDrinks());
	}
		
}
int main()
{
	Context* pContext = new Context(new HotDrinks());	//首先委會一份熱飲的狀態 
	pContext->Request();
	pContext->Request();	//改變狀態 ,要冷飲 
	
	delete pContext;
	pContext = NULL;
	return 0;
}

通過上面的例子我們可以看出,對於一杯奶茶來說,中間可以改變自己的狀態,當然現實生活中奶茶並不是可以隨便改變的,基本上是一錘定音的且不可更改的,要不然誰買單呢?

3、思考

  • 整個過程中state的數量可能會很多,是不是做一個管理所有state的類StateManager會比較好呢,這個類統一管理所有state的切換,外界需要切換狀態時只需要向該類提交申請就好。
  • 整個狀態的切換過程中,我們不停的進行了狀態的申請和釋放,上面的例子狀態只切換兩次,就進行了3次的對象申請和釋放,因此,state應該實現爲一個singleton,避免申請時的內存和時間的消耗

4、UML 結構圖
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章