1. 程式人生 > >設計模式---狀態變化模式之state狀態模式(State)

設計模式---狀態變化模式之state狀態模式(State)

情況 ... 概念 擴展 pen com 耦合 new 發現

前提:狀態變化模式

在組建構建過程中,某些對象的狀態經常面臨變化,如何對這些變化進行有效的管理?同時又維持高層模塊的穩定?“狀態變化”模式為這一個問題提供了一種解決方案。

典型模式

狀態模式:State
備忘錄模式:Memento

一:State狀態模式

(一)概念

允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它的類
狀態模式主要解決的是當控制一個對象狀態的條件表達式過於復雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類中,可以把復雜的判斷邏輯簡化。

(二)動機

在軟件構建過程中,某些對象的狀態如果改變,其行為也會隨之而發生變化
,比如文檔處於只讀狀態,其支持的行為和讀寫狀態支持的行為就可能會完全不同。
如何在運行時根據對象的狀態來透明地更改對象的行為?而不會為對象操作和狀態轉化之間引入緊耦合?
我們將狀態邏輯和動態實現進行分離操作

(三)代碼講解

1.原代碼

enum NetworkState  //狀態枚舉
{
    Network_Open,
    Network_Close,
    Network_Connect,
};

class NetworkProcessor{
    
    NetworkState state;

public:
    
void Operation1(){  //多種操作模式 if (state == Network_Open){  //根據當前網絡狀態,修改下一步的網絡狀態 //********** state = Network_Close; } else if (state == Network_Close){ //.......... state = Network_Connect; } else if (state == Network_Connect){
//$$$$$$$$$$ state = Network_Open; } } public void Operation2(){ if (state == Network_Open){ //********** state = Network_Connect; } else if (state == Network_Close){ //..... state = Network_Open; } else if (state == Network_Connect){ //$$$$$$$$$$ state = Network_Close; } } public void Operation3(){ } };
我們發現if...else..的使用同strategy策略模式十分相像,動態考慮,以後這些狀態會不會出現變化,例如:出現Network_wait狀態後如何變化?
違背了開閉原則,依循strategy模式經驗,抽象基類提出

2.改進代碼,將基類抽出

class NetworkState{

public:
    NetworkState* pNext;
    virtual void Operation1()=0;
    virtual void Operation2()=0;
    virtual void Operation3()=0;

    virtual ~NetworkState(){}
};
class OpenState :public NetworkState{
    
    static NetworkState* m_instance;  //單例模式,因為各個狀態只需要一個
public:
    static NetworkState* getInstance(){
        if (m_instance == nullptr) {
            m_instance = new OpenState();
        }
        return m_instance;
    }

    void Operation1(){
        
        //**********  處理邏輯和上面還是一致的
        pNext = CloseState::getInstance();
    }
    
    void Operation2(){
        
        //..........
        pNext = ConnectState::getInstance();
    }
    
    void Operation3(){
        
        //$$$$$$$$$$
        pNext = OpenState::getInstance();
    }
};
class CloseState:public NetworkState{ }
//...多個狀態對象
把狀態相關的操作,全部編碼到一個狀態對象中
class NetworkProcessor{
    
    NetworkState* pState;  //放的不再是枚舉類型,而是狀態對象
    
public:
    
    NetworkProcessor(NetworkState* pState){
        
        this->pState = pState;
    }
    
    void Operation1(){
        //...
        pState->Operation1();
        pState = pState->pNext;
        //...
    }
    
    void Operation2(){
        //...
        pState->Operation2();
        pState = pState->pNext;
        //...
    }
    
    void Operation3(){
        //...
        pState->Operation3();
        pState = pState->pNext;
        //...
    }

};
是哪種狀態就調用哪種操作
我們只需要關心狀態自身的變化,而不需要去看狀態和NetworkProcessor之間的關系
//擴展,解耦合
class WaitState:public NetworkState{ }  

(四)模式定義

允許一個對象在其內部狀態改變時改變它的行為。從而使對象看起來似乎修改了其行為。 

                                                            ——《設計模式》GoF

(五)類圖(結構)

state和strategy模式非常像,策略模式是一個行為,狀態模式可以是一個也可以是多個行為,當是一個行為是和策略模式基本相同

技術分享圖片

(六)要點總結

1.State模式將所有與一個特定狀態相關的行為都放入一個State的子類對象中,在對象狀態切換時, 切換相應的對象;但同時維持State的接口,這樣實現了具體操作與狀態轉換之間的解耦。

只需要關心操作之後的下一個狀態即可,而不需要去想更多耦合情況

2.為不同的狀態引入不同的對象使得狀態轉換變得更加明確,而且可以保證不會出現狀態不一致的情況,因為轉換是原子性的——即要麽徹底轉換過來,要麽不轉換。

3.如果State對象沒有實例變量,那麽各個上下文可以共享同一個State對象,從而節省對象開銷。

單例模式,節省開銷

設計模式---狀態變化模式之state狀態模式(State)