1. 程式人生 > 其它 >C++設計模式 - 狀態模式(State)

C++設計模式 - 狀態模式(State)

狀態變化模式

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

典型模式

  • State
  • Memento

動機(Motivation)

  • 在軟體構建過程中,某些物件的狀態如果改變,其行為也會隨之而發生變化,比如文件處於只讀狀態,其支援的行為和讀寫狀態支援的行為就可能完全不同。
  • 如何在執行時根據物件的狀態來透明地更改物件的行為?而不會為物件操作和狀態轉化之間引入緊耦合?

模式定義

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

結構

要點總結

  • State模式將所有與一個特定狀態相關的行為都放入一個State的子類物件中,在物件狀態切換時,切換相應的物件;但同時維持State的介面,這樣實現了具體操作與狀態轉換之間的解耦。
  • 為不同的狀態引入不同的物件使得狀態轉換變得更加明確,而且可以保證不會出現狀態不一致的情況 ,因為轉換是原子性的一即要麼徹底轉換過來,要麼不轉換。
  • 如果State物件沒有例項變數,那麼各個.上下文可以共享同一個State物件,從而節省物件開銷。

23種設計模式不比太過於計較它們之間的差異,而更關注他們到底解決的是什麼樣的一個穩定點和變化點的關係問題。這個時候呢模式之間的關係也理順了,學習模式一那麼生搬硬套,它無非是設計上的演化而已,是一種鬆耦合設計的原則演化而已。

可以把state和Strateg看成同一種模式,就是出現問題:if-else,列舉。該怎末轉?用多型的方式實現執行時的改變,具體是什麼模式在開發過程中沒那麼重要。

if-else

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

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;
        //...
    }
};