State模式:
State模式当一个对象的内在状态改变时允许改变其行为,这个对象看起来好像是改变了其类。
State模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,那就没必要使用State模式了。
State模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。通过把各种状态转移逻辑分布到State的子类之间来减少互相间的依赖。当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
State模式典型的结构图为:
State模式的实现代码如下:
//state.h
#ifndef _STATE_H_
#define _STATE_H_
class Context; //前置声明
class State
{
public:
State();
virtual ~State();
virtual void OperationInterface(/*Context* */) = 0;
virtual void OperationChangeState(Context*) = 0;
protected:
bool ChangeState(Context* con,State* st);
};
class ConcreteStateA:public State
{
public:
ConcreteStateA();
virtual ~ConcreteStateA();
virtual void OperationInterface(/*Context* */);
virtual void OperationChangeState(Context*);
protected:
private:
};
class ConcreteStateB:public State
{
public:
ConcreteStateB();
virtual ~ConcreteStateB();
virtual void OperationInterface(/*Context* */);
virtual void OperationChangeState(Context*);
protected:
private:
};
#endif //~_STATE_H_
//State.cpp
#include "State.h"
#include "Context.h"
#include <iostream>
using namespace std;
State::State()
{
}
State::~State()
{
}
void State::OperationInterface(/*Context* con*/)
{
cout<<"State::.."<<endl;
}
bool State::ChangeState(Context* con,State* st)
{
con->ChangeState(st);
return true;
}
void State::OperationChangeState(Context* con)
{
}
ConcreteStateA::ConcreteStateA()
{
}
ConcreteStateA::~ConcreteStateA()
{
}
void ConcreteStateA::OperationInterface(/*Context* con*/)
{
cout<<"ConcreteStateA::OperationInterface......"<<endl;
}
void ConcreteStateA::OperationChangeState(Context* con)
{
OperationInterface(/*con*/);
this->ChangeState(con,new ConcreteStateB());
}
ConcreteStateB::ConcreteStateB()
{
}
ConcreteStateB::~ConcreteStateB()
{
}
void ConcreteStateB::OperationInterface(/*Context* con*/)
{
cout<<"ConcreteStateB::OperationInterface......"<<endl;
}
void ConcreteStateB::OperationChangeState(Context* con)
{
OperationInterface(/*con*/);
this->ChangeState(con,new ConcreteStateA());
}
//context.h
#ifndef _CONTEXT_H_
#define _CONTEXT_H_
class State;
class Context
{
public:
Context();
Context(State* state);
~Context();
void OprationInterface();
void OperationChangState();
protected:
private:
friend class State; //表明在State类中可以访问Context类的private字段
bool ChangeState(State* state);
private:
State* _state;
};
#endif //~_CONTEXT_H_
//context.cpp
#include "Context.h"
#include "State.h"
Context::Context()
{
}
Context::Context(State* state)
{
this->_state = state;
}
Context::~Context()
{
delete _state;
}
void Context::OprationInterface()
{
_state->OperationInterface(/*this*/);
}
bool Context::ChangeState(State* state)
{
this->_state = state;
return true;
}
void Context::OperationChangState()
{
_state->OperationChangeState(this);
}
//main.cpp
#include "Context.h"
#include "State.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
State* st1 = new ConcreteStateA();
Context* con = new Context(st1);
con->OprationInterface();
st1->OperationChangeState(con); // 改变状态
con->OprationInterface();
con->OprationInterface();
return 0;
}
State模式和Strategy模式又很大程度上的相似:它们都有一个Context类,都是通过委托(组合)给一个具有多个派生类的多态基类实现Context的算法逻辑。两者最大的差别就是State模式中派生类持有指向Context对象的引用,并通过这个引用调用Context中的方法,但在Strategy模式中就没有这种情况。因此可以说一个State实例同样是Strategy模式的一个实例,反之却不成立。实际上State模式和Strategy模式的区别还在于它们所关注的点不尽相同:State模式主要是要适应对象对于状态改变时的不同处理策略的实现,而Strategy则主要是具体算法和实现接口的解耦(coupling),Strategy模式中并没有状态的概念(虽然很多时候有可以被看作是状态的概念),并且更加不关心状态的改变了。
State模式很好地实现了对象的状态逻辑和动作实现的分离,状态逻辑分布在State的派生类中实现,而动作实现则可以放在Context类中实现(这也是为什么State派生类需要拥有一个指向Context的指针)。这使得两者的变化相互独立,改变State的状态逻辑可以很容易复用Context的动作,也可以在不影响State派生类的前提下创建Context的子类来更改或替换动作实现。
State模式问题主要是逻辑分散化,状态逻辑分布到了很多的State的子类中,很难看到整个的状态逻辑图,这也带来了代码的维护问题。