乙個物件的行為取決於乙個或多個動態變化的屬性,這樣的屬性叫做狀態,這樣的物件叫做有狀態的物件;這樣的物件狀態是從事先定義好的一系列值中取出來的,當乙個這樣的物件與外部事件產生互動,其內部狀態就會改變,從而使得系統的行為與隨之發生變化。
狀態模式:又稱狀態物件模式(pattern of objects for states),狀態模式是物件的行為模式;允許乙個物件
在其內部狀態改變的時候改變自己的行為,物件看起來似乎修改了自己的類。
在狀態模式中,我們建立表示各種狀態的物件和乙個行為隨著狀態物件改變而改變的 context 物件。
如果不使用狀態模式,那麼就需要適用很多if-else來根據當前狀態做出適當的行為選擇,碼中包含大量與物件狀態有關的條件語句,並且不利於後續增加狀態的擴充套件,不可取。
用一句話來表述,狀態模式把所研究的物件的行為包裝在不同的狀態物件裡,每乙個狀態物件都屬於乙個抽象狀態類的乙個子類。狀態模式的意圖是讓乙個物件在其內部狀態改變的時候,其行為也隨之改變。
state狀態:表示狀態,定義了根據不同狀態進行不同處理的介面,該介面是那些處理內容依賴於狀態的方法集合,對應例項的state類
具體的狀態:實現了state介面,對應具體的狀態類
context:context持有當前狀態的具體狀態的例項,此外,他還定義了供外部呼叫者使用的狀態模式的介面。
題例:萬能糖果公司
我們認為糖果機的控制器需要如下圖般的工作,希望你能用c++語言幫我們實現它,而且需要讓設計能夠盡量有彈性而且好維護,因為將來我們可能要為它增加更多的行為。
這張圖是乙個狀態圖,糖果機的所有狀態有:「沒有25分錢」,「有25分錢」,「糖果售罄」,「售出糖果」,每乙個狀態都代表機器不同的配置,需要某些動作將目前的狀態轉換到另外乙個狀態,要進入另外一種狀態,必須做某些事情。對於糖果機當前任何乙個動作,我們都需要檢查,看看糖果機所處的狀態和動作是否合適。
下面我們按照一般思維來設計糖果機的這些功能,步驟如下:
(1)找出所有的狀態
「沒有25分錢」、「有25分錢」、「糖果售罄」、「售出糖果」
(2)建立乙個例項變數來持有目前的狀態,然後定義每個狀態的值
const
static
int no_quarter =1;
const
static
int has_quarter =2;
const
static
int sold_out =0;
const
static
int sold =3;
int state = sold_out;
3)將所有糖果機系統中可以發生的動作整合起來
根據狀態圖可知,四個狀態對應著四個動作:「投入25分錢」,「退回25分錢」,「轉動曲柄」,「發放糖果」;
這些動作是糖果機的對客戶的介面,糖果機會以機器按鈕的方式讓這些介面與玩家互動,這是你能對糖果機做的事情,呼叫任何乙個動作都會造成狀態的轉換,發放糖果更多是糖果機的內部動作,機器自己呼叫自己。
(4)現在,我們建立了乙個類,它的作用就像是乙個狀態機,對每乙個動作,我們都建立了乙個對應的方法,這些方法利用條件語句來決定在每個狀態內什麼行為是恰當的。每乙個可能的狀態都需要用條件語句檢查,然後對每乙個可能的狀態展現適當的行為。
#include
using
namespace std;
class
gumballmachine
}/* 投入25分錢 */
void
insertquarter()
else
if(state == no_quarter)
else
if(state == sold_out)
else
if(state == sold)
}/* 退回25分錢 */
void
ejectquarter()
else
if(state == no_quarter)
else
if(state == sold)
else
if(state == sold_out)
}/* 轉動曲柄 */
void
turncrank()
else
if(state == sold_out)
else
if(state == sold)
else
if(state == no_quarter)
}/* 發放糖果 */
void
dispense()
else
if(state == sold_out)
else
if(state == sold)
else
}else
if(state == no_quarter)}}
;
上述**if-else多麼的可怕,主要是如果糖果機器以後狀態增多,那麼修改if-else將是乙個巨大的工作量,如果採用狀態模式,在動作發生時委託給當前狀態,將是乙個不錯的選擇,主要分為以下3個步驟:
(1)定義乙個state介面,在這個介面內,糖果機的每個動作都有乙個對應的方法;
(2)為機器的每個狀態實現狀態類,這些狀態類負責在對應的狀態下進行機器的行為;
(3)擺脫老**束縛,取而代之的方式將動作委託到狀態類。
(1)狀態模式描述了物件狀態的變化以及物件如何在每一種狀態下表現出不同的行為。
(2)狀態模式的關鍵是引入了乙個抽象類來專門表示物件的狀態,這個類我們叫做抽象狀態類,而物件的每一種具體狀態類都繼承了該類,並在不同具體狀態類中實現了不同狀態的行為,包括各種狀態之間的轉換。
(1)行為隨狀態改變而改變的場景。
(2)條件、分支語句的代替者。
(1)實現多型行為的好處是顯而易見的,並且很容易新增狀態來支援額外的行為。
(2)在狀態模式中,物件的行為是其狀態中函式的結果,並且在執行時根據狀態改變行為,這就消除了對switch/case 或 if/else 條件邏輯的依賴。
(3)可以提高內聚性,因為狀態特定的行為被聚合到具體的類中,這些類被放在**中的乙個位置。
設計模式 狀態模式 C
狀態模式主要解決當控制乙個物件狀態的轉換的條件表達過於複雜的情況,使得狀態的轉換不依賴於整體的操作。本文將通過乙個具體的例子說明狀態模式的應用。假設下面乙個場景 乙個新任務提交後,先是收集資料,資料收集完成後等等分配一台機器,分配到機器後就可以將此任務部署至此機器後就可以通知相關模組開始工作。先對此...
設計模式 狀態模式 C
狀態模式是產生乙個可以改變其類的物件,通過前端物件狀態的變化來使後端工作的不同物件履行其職責。通過改變乙個物件的狀態,使它的工作物件也發生變化。如果乙個物件在決定它要做什麼之前總是要對當前的 狀態做很多的判斷,那麼就可以考慮使用狀態模式。乙個壞的例子 worker.h include ifndef ...
設計模式 狀態模式(c )
狀態模式適用於 乙個物件有多種狀態,在不同狀態下執行同一操作的行為是不同的。例如,檔案在read only write only write and read 狀態下,執行讀 寫等操作時的行為是不同的。狀態模式基本思想 用動態繫結 執行時繫結,多型,用虛函式實現 代替if else或switch,以...