狀態模式

意圖:
使行爲自動適應狀態的改變,去掉if或者case語句
結構圖:
使用場景:
1.對象收到其他對象的請求時,根據自身的不同狀態做出不同的反應
2.一個操作中含有大量的條件分支語句,並且這些分支依賴於狀態
優點:
1.通過增加State的子類可以容易的增加新的狀態和轉化
2.狀態轉換的時候,Context類中只需要重新綁定一個State變量,無須重新賦值,避免內部狀態不一致
3.State對象可以被共享
缺點:
增加了子類的數目,類之間比較混亂
實現:
1.由誰定義狀態的狀態的轉換:
          (1)Context類中定義後繼狀態以及何時進行轉換
          (2)由State子類定義後繼狀態以及何時進行轉換
2.創建和銷燬State子類對象:
          (1)狀態在運行時是不可知的並且不經常改變狀態時,對象使用時創建不使用時銷燬
          (2)狀態對象含有大量信息且狀態變換頻繁時,在運行前一次創建所有對象,運行時不銷燬,運行結束後銷燬
3.Context類中必須含有一個changeState的改變狀態的方法供State類方法調用
與其他模式關係:
1.State子類通常使用單例模式
2.與策略模式相比:狀態模式相互轉換不是用戶指定的,而是自動轉換,相對安全 

代碼示例:
//
//  TcpState.h
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#ifndef TcpState_h
#define TcpState_h

#include <iostream>
#include <string>
class TcpConnection;
//#include "TcpConnection.h"
using namespace std;
class TcpState
{
public:
    TcpState(){
        cout<<"TcpState初始化"<<endl;
        cout<<instance<<endl;
    }
    virtual ~TcpState(){}
    /*把子類的所有行爲封裝到接口中,每個函數都有一個TcpConnection作爲參數從而訪問TcpConnection中的數據和改變連接的狀態*/
    virtual void transmit(TcpConnection* con,string message){
        cout<<message<<endl;}
    virtual void activeOpen(TcpConnection* con){}
    virtual void passiveOpen(TcpConnection* con){}
    virtual void close(TcpConnection* con){}
    virtual void syschronize(TcpConnection* con){}
    virtual void acknowledge(TcpConnection* con){}
    virtual void send(TcpConnection* con){}
    static void release(){ std::cout<<"TcpState"<<endl;}
protected:
    /*可有可無,其本質就是調用Context方法改變其狀態,可再其方法中實現*/
    void changeState(TcpConnection* con, TcpState* state);
    static TcpState* instance;
};

#endif /* TcpState_h */
//
//  TcpState.cpp
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#include "TcpState.h"
#include "TcpConnection.h"

TcpState* TcpState::instance = 0;
void TcpState::changeState(TcpConnection *con, TcpState *state)
{
    con->changeState(state);
}


//
//  TcpListen.h
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#ifndef TcpListen_h
#define TcpListen_h

#include <iostream>
#include "TcpState.h"

class TcpListen:public TcpState
{
public:
    static TcpListen* getInstace()
    {
        if (instance == nullptr) {
            return new TcpListen;
        }
        return dynamic_cast<TcpListen*>(instance);
    }
    
    static void release()
    {
        if (instance != nullptr) {
            delete instance;
            instance = nullptr;
        }
    }
    
    virtual void send(TcpConnection *con);
private:
    TcpListen(){}
    TcpListen(const TcpListen& );
    TcpListen& operator= (const TcpListen&);
    virtual ~TcpListen(){}
    
    //static TcpState* instance;
};

#endif /* TcpListen_h */

//
//  TcpListen.cpp
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#include "TcpListen.h"
#include "TcpEstablished.h"
using namespace std;
//TcpState* TcpListen::instance = 0;
void TcpListen::send(TcpConnection *con)
{
    cout<<"TcpListen::send"<<endl;
    changeState(con, TcpEstablished::getInstance());
}


//
//  TcpEstablished.h
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#ifndef TcpEstablished_h
#define TcpEstablished_h

#include <iostream>
#include "TcpState.h"

class TcpEstablished:public TcpState
{
public:
    /*單例設計模式*/
    static TcpEstablished* getInstance(){
        if (instance == nullptr) {
            return new TcpEstablished;
        }
        return dynamic_cast<TcpEstablished*>(instance);
    }
    
    static void release(){
        if (instance != nullptr) {
            delete instance;
            instance = nullptr;
        }
    }
    
    virtual void transmit(TcpConnection *con, string message);
    virtual void close(TcpConnection *con);
private:
    TcpEstablished(){}
    virtual ~TcpEstablished(){}
    TcpEstablished(const TcpEstablished& );
    TcpEstablished& operator=(const TcpEstablished& );
    
    //static TcpState* instance;
};

#endif /* TcpEstablished_h */

//
//  TcpEstablished.cpp
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#include "TcpEstablished.h"
#include "TcpListen.h"

using namespace std;
//TcpState* TcpEstablished::instance = 0;
void TcpEstablished::transmit(TcpConnection *con, string message)
{
    cout<<"TcpEstablished::transmit"<<message<<endl;
    changeState(con, TcpListen::getInstace());
    
}

void TcpEstablished::close(TcpConnection *con)
{
    cout<<"TcpEstablished::close"<<endl;
    /*具體定義轉換成哪種狀態,調用TcpConnection類的changeState統一執行*/
    changeState(con, TcpListen::getInstace());
}



//
//  TcpClosed.h
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#ifndef TcpClosed_h
#define TcpClosed_h

#include <iostream>
#include "TcpState.h"

class TcpClosed:public TcpState
{
public:
    static TcpClosed* getInstance(){
        if (instance == nullptr) {
            return new TcpClosed;
        }
        return dynamic_cast<TcpClosed*>(instance);
    }
    
    static void release(){
        if (instance != nullptr) {
            delete instance;
            instance = nullptr;
        }
    }
    
    virtual void activeOpen(TcpConnection *con);
    virtual void passiveOpen(TcpConnection* con);
private:
    TcpClosed(){}
    virtual ~TcpClosed(){}
    TcpClosed(const TcpClosed&);
    TcpClosed& operator= (const TcpClosed&);
    
};

#endif /* TcpClosed_h */

//
//  TcpClosed.cpp
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#include "TcpClosed.h"
#include "TcpEstablished.h"
#include "TcpListen.h"
using namespace std;

void TcpClosed::activeOpen(TcpConnection *con)
{
    cout<<"TcpClosed::activeOpen"<<endl;
    changeState(con, TcpEstablished::getInstance());
}

void TcpClosed::passiveOpen(TcpConnection *con)
{
    cout<<"TcpClosed::passiveOpen"<<endl;
    changeState(con, TcpListen::getInstace());
}


//
//  TcpConnection.h
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#ifndef TcpConnection_h
#define TcpConnection_h

#include <iostream>
#include "TcpState.h"
#include "TcpListen.h"
#include "TcpEstablished.h"
#include "TcpClosed.h"

using namespace std;

class TcpConnection
{
public:
    TcpConnection(){ state = TcpClosed::getInstance(); }
    virtual ~TcpConnection(){ /*state->release();*/}
    
    void activeOpen(){ state->activeOpen(this); }
    void passiveOpen(){ state->passiveOpen(this); }
    void close(){ state->close(this); }
    void send(){ state->send(this); }
    void acknowledge(){ state->acknowledge(this); }
    void synchronize(){ state->syschronize(this); }
    void transmit(string message){ state->transmit(this, message); }
private:
    /*必須要有changeState方法供狀態類來調用改變狀態*/
    void changeState(TcpState *state){this->state = state;}
    friend class TcpState;
private:
    TcpState* state;
    
};

#endif /* TcpConnection_h */

//
//  TcpConnection.cpp
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#include "TcpConnection.h"


客戶端代碼:

//
//  main.cpp
//  textD
//
//  Created by md101 on 15/10/19.
//  Copyright © 2015年 md101. All rights reserved.
//

#include <iostream>
#include "TcpConnection.h"

using namespace std;

int main(int argc, const char * argv[]) {
    
    TcpConnection *con = new TcpConnection();
    con->activeOpen();
    con->transmit("xgdsgdfsg");
    con->send();
    TcpClosed::release();
    TcpEstablished::release();
    TcpListen::release();
    delete con;
    
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章