本文是對於 《設計模式 可複用物件導向軟體的基礎 Erich
Gamma、Richard Helm》一書中的狀態模型例子進行實現,並做了一些說明
引目:
考慮一個表示網路連接的類T C P C o n n e c t i o n。一個T C P C o n n e c t i o n對象的狀態處於若干不同狀態之一: 串連已建立( E s t a b l i s h e d)、正在監聽( L i s t e n i n g )、串連已關閉( C l o s e d )。當一個T C P C o n n e c t i o n對象收到其他對象的請求時,
它根據自身的目前狀態作出不同的反應。例如,一個O p e n請求的結果依賴於該串連是處於串連已關閉狀態還是串連已建立狀態。S t a t e模式描述了T C P C o n n e c t i o n如何在每一種狀態下表現出不同的行為。這一模式的關鍵思想是引入了一個稱為T C P S t a t e的抽象類別來表示網路的串連狀態。T C P S t a t e類為各表示不同的操作狀態的子類聲明了一個公用介面。T C P S t a t e的子類實現與特定狀態相關的行為。例如, TCPEstablished和T
C P C l o s e d類分別實現了特定於T C P C o n n e c t i o n的串連已建立狀態和串連已關閉狀態的行為。
T C P C o n n e c t i o n類維護一個表示T C P串連目前狀態的狀態物件(一個T C P S t a t e子類的執行個體)。T C P C o n n e c t i o n類將所有與狀態相關的請求委託給這個狀態物件。T C P C o n n e c t i o n使用它的T C P S t a t e子類執行個體來執行特定於串連狀態的操作。一旦串連狀態改變, T C P C o
n n e c t i o n對象就會改變它所使用的狀態物件。例如當串連從已建立狀態轉為已關閉狀態時, TCPConnection 會用一個T C P C l o s e d的執行個體來代替原來的T C P E s t a b l i s h e d的執行個體。
狀態模型的設計結構如下:
樣本的實現
1 ) 誰定義狀態轉換S t a t e模式不指定哪一個參與者定義狀態轉換準則。如果該準則是固定的, 那麼它們可在C o n t e x t中完全實現。然而若讓S t a t e子類自身指定它們的後繼狀態以及何時進行轉換, 通常更靈活更合適。這需要C o n t e x t增加一個介面, 讓S t a t e對象顯式地設定C o n t e x t的目前狀態。
2) 基於表的另一種方法在C++ Programming Style[Car92]中, Carg i l描述了另一種將結構載入在狀態驅動的代碼上的方法: 他使用表將輸入映射到狀態轉換。對每一個狀態, 一張表將每一個可能的輸入映射到一個後繼狀態。實際上, 這種方法將條件代碼(和S t a t e模式下的虛函數)映射為一個尋找表。
3 ) 建立和銷毀S t a t e對象一個常見的值得考慮的實現上的權衡是, 究竟是( 1 )僅當需要S t a t e對象時才建立它們並隨後銷毀它們,還是( 2 )提前建立它們並且始終不銷毀它們。
4 ) 使用動態繼承改變一個響應特定請求的行為可以用在運行時刻改變這個對象的類的
辦法實現, 但這在大多數物件導向程式設計語言中都是不可能的。
程式碼範例
代碼是自己照著題意寫的,可能有的 地方不怎麼規範,但基本思想已明確,下是完整的代碼,僅供參考與學習
#include <iostream>enum {S_CLOSE,S_ESTABLISH,S_LISTE };class TCPConnection;class TCPEstablished;class TCPClosed ;class TCPState{public:virtual int ActiveOpen(TCPConnection *tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}virtual int PassiveOpen(TCPConnection *tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}virtual int Connect(TCPConnection *tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}virtual int Close(TCPConnection * tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}virtual int Acknoledge(TCPConnection * tcp){std::cout <<"this type is :"<<_curStatu<<"0:S_CLOSE,1:S_ESTABLISH,2:S_LISTE "<<std::endl; return 0;}virtual int ChageState(TCPConnection * tcp,TCPState * s);public:virtual ~TCPState(){};protected:int _curStatu ;};class TCPEstablished:public TCPState{public:int Close(TCPConnection * tcp);static TCPState* Instance() ;};class TCPListen:public TCPState{public:virtual int Connect(TCPConnection *tcp);virtual int Close(TCPConnection * tcp);static TCPState* Instance() ;};class TCPClosed:public TCPState{public:int PassiveOpen(TCPConnection *tcp);virtual int ActiveOpen(TCPConnection *tcp);static TCPState* Instance();};class TCPConnection{private:TCPState * state ;public:int Init(); int ActiveOpen(); int PassiveOpen();int Connect();int Close() ;int Acknoledge();int ChageState(TCPState * s);};/////////////defines of method for TCPState /////////////////////////////////////////////////////int TCPState::ChageState(TCPConnection * tcp,TCPState * s){tcp->ChageState(s);return 0;}////////////defines of method for classes inherited TCPState/////////////////////////////////////int TCPEstablished::Close(TCPConnection * tcp){std::cout << "change status :Established ---> Close"<<std::endl;tcp->ChageState(TCPClosed::Instance());return 0;}TCPState* TCPEstablished::Instance(){return new TCPEstablished ;}int TCPListen::Connect(TCPConnection *tcp){std::cout << "change status :Listen ---> Established"<<std::endl;tcp->ChageState(TCPEstablished::Instance());return 0;}int TCPListen::Close(TCPConnection * tcp){std::cout << "change status :Listen ---> Close"<<std::endl;tcp->ChageState(TCPClosed::Instance());return 0;}TCPState * TCPListen::Instance(){return new TCPListen ;}int TCPClosed::ActiveOpen(TCPConnection *tcp){std::cout << "change status :Close ---> Established"<<std::endl;tcp->ChageState(TCPEstablished::Instance());return 0;}int TCPClosed::PassiveOpen(TCPConnection *tcp){std::cout << "change status :Close ---> Lisen"<<std::endl;tcp->ChageState(TCPListen::Instance());return 0;}TCPState * TCPClosed::Instance(){return new TCPClosed ;}//////////TCPConnection///////////////////////////////////////////////////int TCPConnection::Init(){state = TCPClosed::Instance();return 0;}int TCPConnection::ActiveOpen(){state->ActiveOpen(this);return 0;}int TCPConnection::PassiveOpen(){state->PassiveOpen(this) ;return 0;}int TCPConnection::ChageState(TCPState * s){if(!state)delete state ;state = s ;return 0;}int TCPConnection::Connect(){state->Connect(this) ;return 0;}int TCPConnection::Close() {state->Close(this);return 0;}int main(int arg,char ** argc){TCPConnection t ;t.Init();t.ActiveOpen();t.Close();t.PassiveOpen();t.ActiveOpen();t.Close();}
小結