state - 状态模式
原理
在<设计模式:可复用对象软件基础>一书中这样描述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模式将每一个条件分支放入一个独立的类中,这个使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化;