状态模式就是升级版的策略模式!它解决的也是程序中常见的条件可能变化的if/else或者switch/case语句,不同的是状态模式在状态发生改变时,其内部会使其指向下一种状态,无需调用者做出选择。这样解释好像还是太抽象了,算了,先看定义吧。
状态模式的定义:允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。
看看上面的定义,是不是更抽象了...
还是用实际程序中例子来解释吧。我们在程序中会常常操作一个网络对象,比如一个TCP的操作,我们会调用诸如Start,Connect,Stop等等的操作,在进行完一个操作后,TCP对象的状态就会改变,这样下一次操作时我们会检测当前TCP对象是什么状态,然后再进行相应的操作。也是就是我们会根据当前TCP对象的状态来进行相应的操作。总之,要是按照正常的思路来写,就是一堆if/else。显然,如果这里的状态很多话,那写起来可就费劲了,搞不好就被自己绕晕了。这个时候就可以亮出状态模式了。
UML结构图如下:
下面我用伪码来表述上面的例子。
//先按照正常写代码的思路来写
//首先,我们有一堆状态,那肯定是枚举了
enum NetState {Net_Start,Net_Connect,Net_Stop};
//下面我们要进行操作了
class TCPProcess
{
protected:
NetState state;//状态对象
public:
void Operation1() {
if(state == Net_Start){
//如果当前状态是....,就.........
//操作完成后改变状态
state = Net_Connect;
}
else if(state == Net_Connect){
//如果当前状态是....,就.........
//操作完成后改变状态
state = Net_Stop;
}
else if(state == Net_Stop){
//如果当前状态是....,就.........
//操作完成后改变状态
state = Net_Start;
}
}
//下面类似,总之就是先判断当前状态,再操作,最后改变当前状态
void Operation2() {}
void Operation3() {}
};
//状态模式闪亮登场。。。
//首先,我们提炼一下这里稳定的部分,即稳定的接口有哪些,那显然是TCP操作本身了
//网络基类
class NetState
{
public:
virtual ~NetState() {}
public:
NetState *pNext;//下一种状态的指针
virtual void Operation1()=0;//不同状态下,可以进行什么样的操作
virtual void Operation2()=0;//不同状态下,可以进行什么样的操作
virtual void Operation3()=0;//不同状态下,可以进行什么样的操作
};
//如果是开始的状态
class StartState : public NetState
{
protected:
static NetState *m_instance;
public:
static NetState *getInstance(){
if(m_instance == NULL){
m_instance = new StartState();
}
return m_instance;
}
void Operation1()
{
//...........
pNext = StopState::getInstance();
}
void Operation2()
{
//...........
pNext = ConnectState::getInstance();
}
void Operation3()
{
//............
pNext = StartState::getInstance();
}
};
//其它的状态类似
class StopState : public NetState {};
class ConnectState : public NetState {};
//下面我们要进行操作了
class TCPProcess
{
protected:
NetState *m_pState;
public:
TCPProcess(NetState *pState):m_pState(pState) {}
void Operation1(){
//...
pState->Operation1();
pState = pState->pNext;
//...
}
void Operation2(){
//...
pState->Operation2();
pState = pState->pNext;
//...
}
void Operation3(){
//...
pState->Operation3();
pState = pState->pNext;
//...
}
};
//现在看这段代码,和策略模式不同的就是我们在内部维护了一个指向下一种状态的指针而已
现在返回那张UML图我们再来看:
结合到我们的例子和状态模式的定义,其中稳定的部分就是我们的网络基类NetState和网络操作类TCPProcess。变化的就是各种各样的实际的网络状态。我们是通过组合的方式(TCPProcess类中包含一个NetState类的指针)实现的多态调用,并且在TCPProcess类中改变NetState类的状态。
最后,如果理解的有偏差,还请指出