StatePattern with C++

状态模式 C++实现

状态模式是一种封装模式,也就是说当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

###它有两种使用情况:(1)一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。(2)一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。如果if-else过于庞大,那么状态模式将是很好的选择。

###之前我的文章都见过这种方式,将具体的实现class都委托给一个封装类来执行,这种方式非常普遍!比如在访问者模式中,通过


void Accept( BaseVisitor *visitor )
{
   visitor->Visit( this );
}

来委托给visitor 执行concrete class! 这种模式适合在权限设计,条件分子判断设计中使用,当然了,也容易造成concrete class 膨胀!

首先,我们要先说单状态的状态模式,这种模式,我们不需要使用if – else语句就可以通过状态切换,达到行为切换!

状态模式的优点在于遵循了很好的开闭原则和单一职责原则,只要修改状态,我们修改一个子类就好了。

但是存在的问题在于如果状态过多,那就会导致子类过多,发生类膨胀,所以在使用这个模式的时候要权衡好状态模式的利弊!

> #include #include using namespace std; class Context; class State { public: virtual void Handle(Context* pContext)=0; ~State(){} protected: State(){} private: }; class Context { public: Context(State* pState){this->_state = pState;} ~Context(){} void Request() { if(NULL != this->_state) { this->_state->Handle(this); } } void ChangeState(State* pState) { this->_state = pState; } protected: private: State* _state; }; class ConcreteStateA; class ConcreteStateC : public State { public: ConcreteStateC(){} ~ConcreteStateC(){} virtual void Handle(Context* pContext) { cout << "ConcreteStateC" << endl; pContext->ChangeState(new ConcreteStateA()); } protected: private: }; class ConcreteStateB : public State { public: ConcreteStateB(){} ~ConcreteStateB(){} virtual void Handle(Context* pContext) { cout << "ConcreteStateB" << endl; pContext->ChangeState(new ConcreteStateC()); } protected: private: }; class ConcreteStateA : public State { public: ConcreteStateA(){} ~ConcreteStateA(){} virtual void Handle(Context* pContext) { cout << "ConcreteStateA" << endl; pContext->ChangeState(new ConcreteStateB()); //execute and change status } protected: private: }; int main() { State* pState = new ConcreteStateA(); Context* pContext = new Context(pState); pContext->Request(); pContext->Request(); pContext->Request(); pContext->Request(); pContext->Request(); return 0; } </code></pre> 接下来,多状态切换,我们使用switch case来判断。 #####另外如果业务需求某项业务有多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的多分支判断语句来实现,此时应该考虑将每一种业务状态定义为一个State的子类。这样这些对象就可以不依赖于其他对象儿独立变化了。 ![](/assets/pic/multiState.png)