1. 程式人生 > >設計模式之狀態STATE模式(C++)

設計模式之狀態STATE模式(C++)

狀態模式:屬於行為型模式的其中一種,其允許一個物件在內部改變狀態時改變它的行為,物件看起來似乎修改了它的類。

狀態模式主要解決的是當控制一個物件的狀態轉換條件表示式過於複雜時的情況,把狀態的邏輯判斷轉移到表示不同狀態的一系列類中,可以把複雜的判斷邏輯簡化。好處就是講於特定狀態相關的行為區域性化,並且將不同的狀態行為分割開來。比如說我們有一個DoSomeThing的函式,該函式內有大量的if else 分支或者case分支,函式在不同的分支下執行不同的操作。在程式設計中有一個基本的準則是程式碼壞味道,就是函式程式碼過長往往是一個壞味道,通常做法是將函式剝離成幾個小函式,而在面向物件中,就可以利用狀態模式,將特性的狀態以及該狀態下的相關行為分割成一個獨立的狀態類,把複雜的狀態邏輯判斷分割開,有利於系統的拓展新,當需要增加條件判斷分支時僅需要增加一個狀態類即可,同時而不需要再原來的函式中增加判斷分支(破壞開放-封閉原則)。

通用STATE模式的UML類圖

Context:定義客戶感興趣的介面,維護一個State的引用,該引用儲存著當前的狀態。

State:抽象狀態類,定義各個狀態下需要執行的相應行為的統一抽象介面。

ConcreteState:具體狀態類,實現抽象State狀態的介面,定義自己狀態下的相關行為。

以一個基本的SOCKET的通訊程式碼為例,寫了一個簡約版的示例程式碼:

State.h

class TCPState;
class TCPConn
{
public:
	TCPConn(TCPState* state){ this->m_state = state; }
	void SetTCPState(TCPState* state);
	void Request();
private:
	TCPState* m_state;
};

class TCPState
{
public:
	virtual void Handle(TCPConn*) = 0;
	virtual ~TCPState(){};
};

class TCPClose : public TCPState
{
public:
	virtual~TCPClose(){};
	virtual void Handle(TCPConn*);
};


class TCPListen :public TCPState
{
public:
	virtual ~TCPListen(){};
	virtual void Handle(TCPConn*);
};

class TCPAccepted :public TCPState
{
public:
	virtual ~TCPAccepted(){};
	virtual void Handle(TCPConn*);
};

class TCPConnected :public TCPState
{
public:
	virtual ~TCPConnected(){};
	virtual void Handle(TCPConn*);
};

State.cpp

#include "State.h"
#include <iostream>
void TCPListen::Handle(TCPConn* tcpConn)
{
	//可以呼叫socket bind, listen等函式
	std::cout << "TCP STAT Listening\n";
	tcpConn->SetTCPState(new TCPAccepted());
}

void TCPAccepted::Handle(TCPConn* tcpConn)
{
	//可以呼叫accepted 等待客戶端連線
	std::cout << "TCP STAT Accepted\n";
	tcpConn->SetTCPState(new TCPConnected());
}

void TCPConnected::Handle(TCPConn* tcpConn)
{
	//可以在這裡寫讀寫函式 send recv
	std::cout << "Tcp STAT connected\n";
	tcpConn->SetTCPState(new TCPClose());
}

void TCPClose::Handle(TCPConn* tcpConn)
{
	//可以再這裡呼叫close 關閉socket
	std::cout << "TCP STAT Close\n";
	tcpConn->SetTCPState(new TCPListen());
}

void TCPConn::SetTCPState(TCPState* state)
{
	if (NULL != m_state)
		delete m_state;
	this->m_state = state;
}

void TCPConn::Request()
{
	m_state->Handle(this);
}

客戶端程式碼:

#include "State.h"

int main()
{
	TCPConn* tcpconn = new TCPConn(new TCPListen());
	tcpconn->Request();
	tcpconn->Request();
	tcpconn->Request();
	tcpconn->Request();
	delete tcpconn;
}

程式碼執行截圖: