State.cpp
#include "State.h"
#include <iostream>
using namespace std;
State::State()
{}
State::~State()
{}
ConcreteStateA::ConcreteStateA()
{}
ConcreteStateA::~ConcreteStateA()
{}
//执行该状态的行为并改变状态
void ConcreteStateA::Handle(Context* pContext)
{
cout << "ConcreteStateA" << endl;
pContext->ChangeState(new ConcreteStateB());
}
ConcreteStateB::ConcreteStateB()
{}
ConcreteStateB::~ConcreteStateB()
{}
//执行该状态的行为并改变状态
void ConcreteStateB::Handle(Context* pContext)
{
cout << "ConcreteStateB" << endl;
pContext->ChangeState(new ConcreteStateC());
}
ConcreteStateC::ConcreteStateC()
{}
ConcreteStateC::~ConcreteStateC()
{}
//执行该状态的行为并改变状态
void ConcreteStateC::Handle(Context* pContext)
{
cout << "ConcreteStateC" << endl;
pContext->ChangeState(new ConcreteStateA());
}
//定义_state的初始状态
Context::Context(State* pState)
{
this->_state = pState;
}
Context::~Context()
{}
//对请求做处理,并设置下一状态
void Context::Request()
{
if(NULL != this->_state)
{
this->_state->Handle(this);
}
}
//改变状态
void Context::ChangeState(State* pState)
{
this->_state = pState;
}
main.cpp
#include "State.h"
int main()
{
State* pState = new ConcreteStateA();
Context* pContext = new Context(pState);
pContext->Request();
pContext->Request();
pContext->Request();
pContext->Request();
pContext->Request();
return 0;
}
总结
对于状态模式,很多情况下和策略模式看起来极为相似。实际上它们都是为了解决具体子类实现抽象接口的实现异构问题而存在的(封装变化),但是它们的侧重各不相同。而针对算法的异构问题,模板方法模式通过继承的方式来改变一部分算法实现(原子操作在不同具体子类中可以有不同实现),策略模式则通过组合的方式来改变整个算法(可动态替换),而状态模式则强调的是针对不同的状态对象可以有不同的响应。因此状态模式实际上强调的状态的概念,并且强调对状态转换的逻辑封装,即对象可能处于不同的状态下,而各个状态在响应了该状态的实现后可能会动态转到另一个状态,而这个转变我们不希望 Context 的参与(Context 不必维护这个转换)。状态机在编译原理的 DFA/NDFA 中很常见,针对一个输入字符和已有串,DFA/NDFA 可能会转换到另外一个状态。
因此对于状态模式有以下几个关键点:
1. 状态模式会处理算法的不同,但是更加关注的是状态的改变。并且对于状态的转变逻辑一般会放在 State 子类中实现。而对于不同状态的处理则可以放在 Context 类中,State 子类保存一个指向 Context 的引用(实际上往往传递一个指向 Context 的指针即可,而不必在 State 子类真正保存一个引用),以调用这些实现。当然放在 State 子类中实现也无可厚非,不过为了突出重点,使用前一种方式实现更能说明问题。当然在实际开发中,完全可以不受这个制约。










