原理

在<设计模式:可复用对象软件基础>一书中这样描述TCPConnection的状态变化如何使用状态模式:
1.一个TCPConnection会有连接已建立(Established),正在监听(Listening),连接已关闭这几个状态,那么在其他对象使用TCPConnection使用它时,它要根据自身的状态作出不同的反应;
2.为了不将各个状态的实际操作暴露,引入TCPState的抽象类,TCPState为个表示不同的操作状态的子类声明公共接口,其中子类的实现与特定的状态相关的行为;
3.TCPState抽象网络连接状态接口,在c++中可以使用虚函数的方式,为了TCPState完全抽象,建议设置为纯虚类(不能实例化);
4.TCPConnection类维护一个TCPState(例如:TCPEstablished)子类的实例,TCPConnection所有的操作都委托给TCPState(例如:TCPEstablished)子类的实例,其中内部的状态转移和实例替换全部都被TCPEstablished封装,那么说了这么多,其实看代码最透彻;

实例代码

// 精简<设计模式:可复用对象软件基础>代码,没有重写一个栗子的原因是TCP状态转移是state设计模式最好的表现

// 需要操作的类
class TCPConnection
{
public:
	TCPConnection()
	{
		state_ = TCPClosed::Instance();
	}

	void Connect() // 连接
	{
		state_->ActiveOpen(this);
	}
	void Send() // 发送数据
	{
		state_->Send(this);
	}
	void Close() // 关闭连接
	{
		state_->Close(this);
	}
	void Process(void* data); // 处理实际数据

private:
	friend class TCPState;
	void ChangeState(TCPState* s)
	{
		state_ = s;
	}

private:
	TCPState* state_;
};
class TCPState
{
public:
	virtual void Transmit(TCPConnection* ,void* );
	virtual void Send(TCPConnection*);
	virtual void Close(TCPConnection*);
	virtual void ActiveOpen(TCPConnection*);
	virtual void PassiveOpen(TCPConnection*);

protected:
	void ChangeState(TCPConnection* t, TCPState* s)
	{
		t->ChangeState(s); // 改变TCPState
	}
};
class TCPEstablished : public TCPState
{
public:
	static TCPState* Instance();

	virtual void Transmit(TCPConnection* t, void* data)
	{
		// ... 实际处理逻辑
		t->Process(data); // 处理完数据
	}
	virtual void Close(TCPConnection* t)
	{
		// ... 实际处理逻辑
		ChangeState(t, TCPListened::Instance());
	}

private:
	static TCPEstablished* instance_;
};
class TCPListened : public TCPState
{
public:
	static TCPState* Instance();

	virtual void Send(TCPConnection* t)
	{
		// ... 实际处理逻辑
		ChangeState(t, TCPEstablished::Instance());		
	}

private:
	static TCPListened* instance_;
};
class TCPClosed : public TCPState
{
public:
	static TCPState* Instance();

	virtual void ActiveOpen(TCPConnection* t)
	{
		// ... 实际处理逻辑
		ChangeState(t, TCPEstablished::Instance());	
	}
	virtual void PassiveOpen(TCPConnection* t)
	{
		// ... 实际处理逻辑
		ChangeState(t, TCPListened::Instance());	
	}

private:
	static TCPClosed* instance_;
};

state模式使用场景

state模式适用以下场景:
1.一个对象的行为取决于他的状态,并且它必须在运行时根据状态改变它的行为;
2.一个操作中包含多个分支,分支又依赖对象的状态,这个对象通常用一个或者多个枚举常量表示,通常多个操作包含这一相同的条件结构,State模式将每一个条件分支放入一个独立的类中,这个使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化;