“狀態變化”模式
在組件構建程序中,某些物件的狀態經常面臨變化,如何對這些變化進行有效的管理?同時又維持高層模塊的穩定?“狀態變化”模式應運而生,
典型模式 :State、 Memento
State 狀態模式
在實際開發中,經常會遇到,一個物件有多種狀態,在每一個狀態下,都有不同的行為,如下:
1 typedef enum tagState 2 { 3 state0, 4 state1, 5 state2 6 }State; 7 8 //根據不同的state執行不同的DoSomrthing,就實際上相當于不同的Handle 9 void Handle(State state) 10 { 11 if (state == state0){ 12 // DoSomethingA 13 } else if (state == state1){ 14 // DoSomethingB 15 } else if (state == state2){ 16 // DoSomethingC 17 }else { 18 // DoSomethingD 19 } 20 } 21 22 //等效于根據不同的state呼叫不同的Handle 23 void Handle(state0) { //Do somethingA } 24 void Handle(state1) { //Do somethingB } 25 void Handle(state2) { //Do somethingC } 26 void Handle(other) { //Do somethingD }
每當新增狀態時,就需要添加if-else分支,修改原來的代碼,違反“開閉原則”,而且大量的分支結構,使得代碼難以理解與維護,
動機
- 在軟體構建程序中,某些物件的狀態如果改變,其行為也會隨之而發生變化,比如檔案處于只讀狀態,其支持的行為和讀寫狀態支持的行為就可能完全不同,
- 如何在運行時根據物件的狀態來透明地更改物件的行為?而不會為物件操作和狀態轉換之間引入緊耦合?
定義
允許一個物件在其內部狀態改變時改變它的行為,從而使物件看起來似乎修改了其行為, ——《設計模式》GOF
有了狀態模式之后,可以解決隨著狀態增加而出現的多分支結構,將狀態處理分散到各個狀態子類中去,每個子類處理一種狀態,因而使得狀態的處理和轉換變得清晰明確,
結構

Context:定義客戶端感興趣的介面,并且維護一個ConcreteState子類的實體,這個實體定義當前狀態;
State:定義一個介面以封裝與Context的一個特定狀態相關的行為;
ConcreteState A/B:每一個子類實作一個與Context的一個狀態相關的行為,
它們之間的協作步驟:
- Context將與狀態相關的請求委托給當前的ConcreteState物件處理;
- Context可以將自身作為一個引數傳遞給處理該請求的狀態物件,這使得狀態物件可以在必要時訪問Context;
- Context是客戶使用的主要介面,客戶可用狀態物件來配置一個Context,一旦一個Context配置完畢,它的客戶不再需要直接與狀態物件打交道,
代碼實作:
1 #include <iostream> 2 using namespace std; 3 4 class Context; 5 6 //狀態基類,為不同的狀態規范統一的介面,當然可以有Handle1,Handle2... 7 class State { 8 public: 9 virtual void Handle(Context* pContext) = 0; 10 }; 11 12 //如最開始的實體代碼,將if-else拆散為不同狀態下的Handle處理函式 13 class ConcreteStateA : public State { 14 public: 15 virtual void Handle(Context* pContext) { cout << "I am concreteStateA\n"; } 16 }; 17 18 class ConcreteStateB : public State { 19 public: 20 virtual void Handle(Context* pContext) { cout << "I am concreteStateB\n"; } 21 }; 22 23 //客戶使用的主要介面,用狀態物件來配置一個Context 24 class Context { 25 public: 26 Context(State* pState) : m_pState(pState) {} 27 28 //根據多型的特性會實際呼叫到指定狀態的處理函式 29 void Request() { 30 if (m_pState) { 31 m_pState->Handle(this); 32 } 33 } 34 35 void ChangState(State* pState) { m_pState = pState; } 36 37 private: 38 State* m_pState; 39 }; 40 41 int main() { 42 State* pStateA = new ConcreteStateA(); 43 State* pStateB = new ConcreteStateB(); 44 Context* pContext = new Context(pStateA); 45 pContext->Request(); 46 pContext->ChangState(pStateB); 47 pContext->Request(); 48 49 delete pContext; 50 delete pStateB; 51 delete pStateA; 52 53 return 0; 54 }
總結
狀態模式是利用多型的動態系結特性消除了if-else的分支結構,將物件的狀態與對應狀態下的行為分離開來,每一個狀態對應一個類,一個類集中管理一個狀態,在多狀態的情況下,簡化程式的結構,易于擴展,
參考:
C++設計模式——狀態模式
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/347036.html
標籤:設計模式
