天天看點

[設計模式筆記]三. 行為型模式--22. State模式(狀态)對象行為型模式(一)一. 意圖二. 适用性三. 模式結構四. 角色說明五. 說明六. 我的了解七. 相關模式

行為型模式--State模式(狀态)對象行為型模式

一. 意圖

允許一個對象在其内部狀态改變時改變它的行為. 對象看起來似乎修改了它的類.

(狀态與行為綁定, 狀态變了, 行為也就随之改變.).

二. 适用性

在下面的兩種情況下均可使用State模式:

一個對象的行為取決于它的狀态, 并且它必須在運作時刻根據狀态改變它的行為.

一個操作中含有龐大的多分支的條件語句, 且這些分支依賴于該對象的狀态. 這個狀态通常用一個或多個枚舉常量表示. 通常,  有多個操作包含這一相同的條件結構. State模式将每一個條件分支放入一個獨立的類中. 這使得你可以根據對象自身的情況将對象的狀态作為一個對象, 這一對象可以不依賴于其他對象而獨立變化..

三. 模式結構

[設計模式筆記]三. 行為型模式--22. State模式(狀态)對象行為型模式(一)一. 意圖二. 适用性三. 模式結構四. 角色說明五. 說明六. 我的了解七. 相關模式

圖1 

四. 角色說明

Context(上下文)

—定義客戶感興趣的接口。

—維護一個ConcreteState子類的執行個體, 這個執行個體定義目前狀态.

State(狀态)

—定義一個接口以封裝與Context的一個特定狀态相關的行為.

ConcreteState subclasses(具體狀态子類)

—每一子類實作一個與Context的一個狀态相關的行為.

協作

Context将與狀态相關的請求委托給目前的ConcreteState對象處理.

Context可将自身作為一個參數傳遞給處理該請求的狀态對象. 這使得狀态對象在必要時可通路Context.

Context是客戶使用的主要接口. 客戶可用狀态對象來配置一個Context, 一旦一個Context配置完畢, 它的客戶不再需要直接與狀态對象打交道.

Context或ConceteState子類都可決定哪個狀态是另外哪一個的後繼者, 以及是在何種條件下進行狀态轉換.

五. 說明

1. State模式将所有與一個特定的狀态相關的行為都放入一個對象中, 通過定義新的子類可以很容易的增加新的狀态和轉換.

2. State模式将不同狀态的行為分布在多個State子類中. 這就增加了子類的數目, 相對于單個類的實作來說不夠緊湊.

3. 它使得狀态轉換顯式化, 為不同的狀态引入獨立的對象使得轉換變得更加明确.

4. State對象可被共享.(使用Flyweight模式). 

六. 我的了解

1. 在寫一個程式時, 程式的狀态非常重要, 通常程式需要根據目前的狀态來做對應的事情. 很常用的方法是, 使用一個值代表一個狀态, 例如int nState = 0;等, 然後使用if或者switch來判斷nState的值, 根據它的值做不同的事情.

2. 在State模式中, 狀态則使用一個類對象表示, 一個狀态就有一個類(運作時是類對象), 并且該類中有對應該類要做的事情的執行代碼(狀态與對應的行為被綁定在語言層次上, 而不是通過if/switch綁定在代碼層次上).

3. 根據State模式的結構圖. 

例如:

class Context
{
public:
	...
	void SetState(State* pState);
	void Request();
private:
	State* m_pState;
};
...
void Context::SetState(State* pState)
{
	m_pState = pState;
}

void Context::Request()
{
	if(m_pState)
	{
		m_pState->Handle();
	}
}

/
class State
{
public:
	...
	virtual void Handle();
};


class ConcreteStateA
{
public:
	...
	virtual void Handle();
};

void ConcreteStateA::Handle()
{
	int i = 0;
}

class ConcreteStateB
{
public:
	...
	virtual void Handle();
};

void ConcreteStateB::Handle()
{
	int k = 0;
}
......

// Client
// 調用(在某種情況下, Context的狀态被改變了)
// 狀态綁定
pContext->SetState(new ConcreteStateB);
...
// 執行Context目前狀态的行為
pContext->Request();
           

4. 在實際應用中, a. 我們需要删除不使用的狀态(狀态改變時,,需要删除前一個狀态對象), 但是如果狀态變化很頻繁而且狀态對象比較大時, 頻繁的删除會帶來開銷.(可以使用Flyweight模式, 如果條件滿足的話.) b. Handle()函數可以有一些參數, 看需求.

5. State模式中把各個狀态的操作分布到各個具體State子類中. 如果不使用State模式, 這些行為可能就集中到一個類中了.

6. 這種模式不隻是用到狀态的改變中, 例如曾經做過一個服務端, 它接收不同指令, 根據指令的不同來做不同的事情. 那實作的時候, 也可以使用這種模式, 一個指令對應一個類, 類中執行該指令對應的行為. 這場景與State模式是一緻的.

七. 相關模式

Flyweight模式解釋了何時以及怎樣共享狀态對象. 狀态對象通常是Singleton.

繼續閱讀