设置模式之状态模式
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200815170047751.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lvdXphaTIwMTc=,size_16,color_FFFFFF,t_70#pic_center)
上图学过网络的同学应该都比较清楚吧,这是一张TCP状态转换图,只要理解上图,那么对状态模式也就很容易理解啦。
状态模式的意图
允许一个对象在其内部状态改变时改变它的行为。简单的说就是:一个人他的外表没有改变,但是他内在的心里状态发生了改变,那他之后的行为就像变了一个人似的;就好比,一个帅哥在追女神的时候,内心无比激动,“舔狼”本色尽显,这时候他的行为时,说话细声细语,对人关怀备至;然而女神的屌丝男友来了,那这个时候,帅哥内心有起伏变化了,行为变得粗鲁无礼,说话也是粗声粗语;人还是那个人,但是内心的状态变化让他的行为举止变了,当然状态的变化时需要一些触发的,下面我们来看看状态模式的细节吧。
状态模式的动机
一个网络连接的类TCPConnection,这个TCPConnection对象的状态处于若干不同状态之一:连接已建立(Established),正在监听(Listening),连接已关闭(Closed)等等。当一个TCPConnection对象收到其他对象请求时,它会根据当前状态做出不同的反应。
这一模式的关键思想是引入了一个称为TCPState的抽象类来表示网络的连接状态。TCPState类为各表示不同的操作状态的子类声明了一个公共接口。
状态模式的使用场景
- 一个对象的行为取决于它的状态,它必须在运行时根据状态改变它的行为。
- 一个操作中含有庞大的多分支条件语句,且这些分支依赖于该对象的状态。
状态模式的结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200815170027200.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lvdXphaTIwMTc=,size_16,color_FFFFFF,t_70#pic_center)
Context(环境,如TCP Connection)
定义用户感兴趣的接口。
维护一个ConcreteState子类的实例,这个实例表示当前状态。
State(状态,如TCPState)
定义一个接口以封装与Context的一个特定状态相关的行为。
ConcreteState subClasses(具体状态类,如TCPEstablished,TCPClosed)
每一个子类实现一个Context的一个状态相关的行为。
示例代码(不可运行)
/* 头文件 */
class TCPState;
class TCPConnection {
public:
TCPConnection(); /* 构造函数 */
/* 操作 */
void ActiveOpen();
void PassiveOpen();
void Close();
void Send();
void Acknowledge();
void Synchronize();
void ProcessOctet(TCPOctetStream*);
private:
friend class TCPState; /* 友元类 */
void ChangeState(TCPState*);
private:
TCPState* _state; /* 状态 */
};
/* 状态类,最重要的类,主要是用来表示TCPConnection的状态的类 */
/* 这里的状态转换都是通过具体类内部进行的转换,不需要TCPConnection来维持 */
class TCPState {
public:
virtual void Transmit(TCPConnection*, TCPOctetStream*);
virtual void ActiveOpen(TCPConnection*);
virtual void PassiveOpen(TCPConnection*);
virtual void Close(TCPConnection*);
virtual void Synchronize(TCPConnection*);
virtual void Acknowledge(TCPConnection*);
virtual void Send(TCPConnection*);
protected:
void ChangeState(TCPConnection*, TCPState*);
};
class TCPOctetStream {};
/* 具体的状态类 */
class TCPClosed : public TCPState {
public:
static TCPState* Instance();
virtual void ActiveOpen(TCPConnection*);
virtual void PassiveOpen(TCPConnection*);
};
class TCPEStablished : public TCPState {
public:
static TCPState* instance();
virtual void Transmit(TCPConnection*, TCPOctetStream*);
virtual void Close(TCPConnection*);
};
class TCPListen : public TCPState {
public:
static TCPState* Instance();
virtual void send(TCPConnection*);
};
/* TCPConnection.cpp */
#include "TCPConnection.h"
#include "TCPClosed.h"
#include "TCPEstablished.h"
#include "TCPListen.h"
#include <iostream>
TCPConnection::TCPConnection() {
_state = TCPClosed::Instance();
}
void TCPConnection::ChangeState(TCPState* s) {
_state = s;
}
void TCPConnection::ActiveOpen() {
_state->ActiveOpen(this);
}
void TCPConnection::PassiveOpen() {
_state->PassiveOpen(this);
}
void TCPConnection::Close() {
_state->Close(this);
}
void TCPConnection::Acknowledge() {
_state->Acknowledge(this);
}
void TCPConnection::Synchronize() {
_state->Synchronize(this);
}
void TCPConnection::Send() {
_state->Send(this);
}
void TCPConnection::ProcessOctet(TCPOctetStream* o) {
std::cout << "processOctet" << std::endl;
}
/* TCPState.cpp */
#include "TCPState.h"
void TCPState::Transmit(TCPConnection*, TCPOctetStream*) {}
void TCPState::ActiveOpen(TCPConnection*) {}
void TCPState::PassiveOpen(TCPConnection*) {}
void TCPState::Close(TCPConnection*) {}
void TCPState::Synchronize(TCPConnection*) {}
void TCPState::ChangeState(TCPConnection* t, TCPState* s) {
t->ChangeState(s);
}
/* 具体状态类的cpp */
/* 这里的具体实例的Instance()函数都是使用单例模式来实现的 */
void TCPClosed::ActiveOpen(TCPConnection *t){
ChangeState(t,TCPEstablished::Instance());
}
void TCPClosed::PassiveOpen(TCPConnection* t){
ChangeState(t,TCPListen::Instance());
}
void TCPEstablished::Close(TCPConnection *t){
ChangeState(t,TCPCLose::Instance());
}
void TCPEstablished::Transmit(TCPConnection* t, TCPOctetStream* o){
t->processOctet(o);
}
void TCPListen::Send(TCPConnection *t){
ChangeState(t,TCPEstablished::Instance());
}
上面代码锁表示的状态转换图:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200815170004554.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lvdXphaTIwMTc=,size_16,color_FFFFFF,t_70#pic_center)