通过简单的十字专门的状态机,一步步从简单设计到运用设计原则和设计模式的实现。代码一步步抽象/重构,注释中详细说明了每一步抽象和重构的意义。代码可以拷贝编译完整运行。
#include <iostream> #include <vector> #include <assert.h> using namespace std; typedef enum { LOCKED, UNLOCKED, }State; typedef enum { COIN, PASS }Event; #if 0 //原始实现,一个类,switch/case实现状态切换,状态切换里面直接实现Action class Turnstile { public: int state = LOCKED; void HandleEvent(Event event) { switch (state) { case LOCKED: switch (event) { case COIN: cout << "lock (event:coin)-> unlock" << endl; state = UNLOCKED; break; case PASS: cout << "Pass when locked, alarm!" << endl; //state not change break; default: break; } break; case UNLOCKED: switch (event) { case COIN: cout << "unlock (event:coin)-> unlock" << endl; //state not change break; case PASS: cout << "unlock (event:pass)-> lock" << endl; state = LOCKED; break; default: break; } break; default: break; } } }; int main(int argc, char** argv) { Turnstile turnstile; turnstile.state = LOCKED; turnstile.HandleEvent(PASS); assert(turnstile.state == LOCKED); turnstile.state = UNLOCKED; turnstile.HandleEvent(PASS); assert(turnstile.state == LOCKED); } #endif #if 0//第一步抽象,把不易变的状态逻辑放在父类,Action提取出来。当有需求要求变更Action时,增加子类即可,符合开放封闭原则。但这种方式只对Action的改变符合OCP,对状态机结束状态的改变不符合OCP class AbstractTurnstile { public: int state = LOCKED; virtual void Unlock() = 0; virtual void Lock() = 0; virtual void Alarm() = 0; virtual void ThankYou() = 0; void HandleEvent(Event event) { switch (state) { case LOCKED: switch (event) { case COIN: Unlock(); state = UNLOCKED; break; case PASS: Alarm(); //state not change break; default: break; } break; case UNLOCKED: switch (event) { case COIN: ThankYou(); //state not change break; case PASS: Lock(); state = LOCKED; break; default: break; } break; default: break; } } }; class ACustomerTurnstile : public AbstractTurnstile { virtual void Unlock() { cout << "lock (event:coin)-> unlock" << endl; } virtual void Lock() { cout << "unlock (event:pass)-> lock" << endl; } virtual void Alarm() { cout << "Pass when locked, alarm!" << endl; } virtual void ThankYou() { cout << "unlock (event:coin)-> unlock" << endl; } }; int main(int argc, char** argv) { AbstractTurnstile *pTurnstile = new ACustomerTurnstile; pTurnstile->state = LOCKED; pTurnstile->HandleEvent(PASS); assert(pTurnstile->state == LOCKED); pTurnstile->state = UNLOCKED; pTurnstile->HandleEvent(PASS); assert(pTurnstile->state == LOCKED); delete pTurnstile; } #endif #if 0//另一种抽象方式:不用继承而用聚合,把所有Action封装成一个TurnstileAction接口,作为父类指针传进Turnstile类中,状态切换时调用它。 //客户程序(main函数)中派生一个具体TurnstileAction类实现这四个接口 class TurnstileAction { public: virtual void Unlock() = 0; virtual void Lock() = 0; virtual void Alarm() = 0; virtual void ThankYou() = 0; }; class Turnstile { public: int state = LOCKED; TurnstileAction* pAction = NULL; Turnstile(TurnstileAction* pAct) { pAction = pAct; } void HandleEvent(Event event) { switch (state) { case LOCKED: switch (event) { case COIN: pAction->Unlock(); state = UNLOCKED; break; case PASS: pAction->Alarm(); //state not change break; default: break; } break; case UNLOCKED: switch (event) { case COIN: pAction->ThankYou(); //state not change break; case PASS: pAction->Lock(); state = LOCKED; break; default: break; } break; default: break; } } }; int main(int argc, char** argv) { //定义具体用户程序需要的Action class ACustomerAction : public TurnstileAction { virtual void Unlock() { cout << "lock (event:coin)-> unlock" << endl; } virtual void Lock() { cout << "unlock (event:pass)-> lock" << endl; } virtual void Alarm() { cout << "Pass when locked, alarm!" << endl; } virtual void ThankYou() { cout << "unlock (event:coin)-> unlock" << endl; } }; //以此Action作为Turnstile的动作 ACustomerAction action; Turnstile turnstile(&action); //运行Turnstile turnstile.state = LOCKED; turnstile.HandleEvent(PASS); assert(turnstile.state == LOCKED); turnstile.state = UNLOCKED; turnstile.HandleEvent(PASS); assert(turnstile.state == LOCKED); } #endif #if 0//第二步抽象,提取出状态迁移表,这样状态机的改变就只需要更改这个表和具体的TurnstileAction对象,不会更改原有框架代码,符合OCP /*//第一步思路:直接Turnstile里面实现状态机逻辑和状态迁移表的建立 typedef void(*Action)(); class TurnstileAction { public: static void Unlock() { cout << "lock (event:coin)-> unlock" << endl; } static void Lock() { cout << "unlock (event:pass)-> lock" << endl; } static void Alarm() { cout << "Pass when locked, alarm!" << endl; } static void ThankYou() { cout << "unlock (event:coin)-> unlock" << endl; } }; class Transition { public: Transition(int inCurrentState, int inEvent, int inNewState, Action inAction) : currentState(inCurrentState), event(inEvent), newState(inNewState), action(inAction) {;} int currentState; int event; int newState; Action action; }; class Turnstile { public: int state = LOCKED; vector<Transition> trans; Turnstile() { //初始化时添加状态迁移表:当前状态,事件,新状态,动作 AddTransition(LOCKED, COIN, UNLOCKED, TurnstileAction::Unlock); AddTransition(LOCKED, PASS, LOCKED, TurnstileAction::Alarm); AddTransition(UNLOCKED, COIN, UNLOCKED, TurnstileAction::ThankYou); AddTransition(UNLOCKED, PASS, LOCKED, TurnstileAction::Lock); } void HandleEvent(Event event) { for (unsigned int i = 0; i < trans.size(); i++) { Transition* pTrans = &(trans[i]); if (state == pTrans->currentState && event == pTrans->event) { state = pTrans->newState; pTrans->action(); } } } private: void AddTransition(int currentState, int event, int newState, Action action) { trans.push_back(Transition(currentState, event, newState, action)); } }; */ //重构:把不变的状态机逻辑抽象成父类,变化的部分(状态表建立,Action的具体实现)都拿出来子类中实现 //父类,不变的部分 typedef void(*Action)(); class Transition { public: Transition(int inCurrentState, int inEvent, int inNewState, Action inAction) : currentState(inCurrentState), event(inEvent), newState(inNewState), action(inAction) { ; } int currentState; int event; int newState; Action action; }; class StateMachine { public: int state; vector<Transition> trans; void HandleEvent(Event event) { for (unsigned int i = 0; i < trans.size(); i++) { Transition* pTrans = &(trans[i]); if (state == pTrans->currentState && event == pTrans->event) { state = pTrans->newState; pTrans->action(); } } } protected: void AddTransition(int currentState, int event, int newState, Action action) { trans.push_back(Transition(currentState, event, newState, action)); } }; //子类,实现变化的部分 class Turnstile : public StateMachine { public: //所有Action的具体实现 static void Unlock() { cout << "lock (event:coin)-> unlock" << endl; } static void Lock() { cout << "unlock (event:pass)-> lock" << endl; } static void Alarm() { cout << "Pass when locked, alarm!" << endl; } static void ThankYou() { cout << "unlock (event:coin)-> unlock" << endl; } //状态迁移表的建立 Turnstile() { //初始化时添加状态迁移表:当前状态,事件,新状态,动作 AddTransition(LOCKED, COIN, UNLOCKED, Unlock); AddTransition(LOCKED, PASS, LOCKED, Alarm); AddTransition(UNLOCKED, COIN, UNLOCKED, ThankYou); AddTransition(UNLOCKED, PASS, LOCKED, Lock); } }; int main(int argc, char** argv) { //以此Action作为Turnstile的动作 Turnstile turnstile; //运行Turnstile turnstile.state = LOCKED; turnstile.HandleEvent(PASS); assert(turnstile.state == LOCKED); turnstile.state = UNLOCKED; turnstile.HandleEvent(PASS); assert(turnstile.state == LOCKED); } #endif #if 1/*状态模式实现,没啥作用,唯一的好处是把某个状态的所有行为放在一个具体的状态类中,一定程度上隔离了各状态的行为。 代价非常高昂:1.大量的派生类,2.逻辑分散,每增加或修改一个状态迁移,需要改所有的代码(State接口,具体State类,Turnstile类),非常难以修改/扩展/维护 以我的感觉和项目中遇到的2处状态机实现,STATE模式没什么吊用,状态迁移表才是最实用最有效的。 更悲剧的是,STATE模式用C++实现会有循环依赖问题!Turnstile和TurnstileLockedState之间循环依赖了,无法编译通过。还要搞点妖蛾子才能编译通过, 解除循环依赖编译问题参考http://zhidao.baidu.com/link?url=5jzADbx87CLFt_NihyAO79FwIFGFwDWW5VZsOgH-AU77ZdC-Hga5PgVlVkJiu7aVigim3LSuZ9EdSiTCB2Ul1_ 或者用头文件方式http://www.cnblogs.com/wanggary/archive/2011/04/21/2024117.html和*/ class Turnstile; class TurnstileState; class TurnstileLockedState; class TurnstileUnlockedState; //抽象状态,定义一个状态,里面给出对所有事件的处理接口 class TurnstileState { public: virtual void CoinEvent(Turnstile* pTs) = 0; virtual void PassEvent(Turnstile* pTs) = 0; }; //具体状态,定义各个具体状态及其对各种事件的处理。因为循环依赖的原因,不能直接在这里实现,在Turnstile类定义之后实现 class TurnstileLockedState : public TurnstileState { public: virtual void CoinEvent(Turnstile* pTs); virtual void PassEvent(Turnstile* pTs); }; class TurnstileUnlockedState : public TurnstileState { public: virtual void CoinEvent(Turnstile* pTs); virtual void PassEvent(Turnstile* pTs); }; //Context类,用于保存当前的状态和实现具体的状态切换和Action class Turnstile { private: TurnstileState* pState = NULL; TurnstileLockedState lockedState; TurnstileUnlockedState unlockedState; public: Turnstile() { pState = &lockedState; } void SetState(State state) {//这里仍然用到了条件判断,可以重构成表形式 if (state == UNLOCKED) { pState = &unlockedState; } else { pState = &lockedState; } } void CoinEvent() { pState->CoinEvent(this); } void PassEvent() { pState->PassEvent(this); } //Action函数,可以提出来用单独的一个TurnstileAction类来实现 void Unlock() { cout << "lock (event:coin)-> unlock" << endl; } void Lock() { cout << "unlock (event:pass)-> lock" << endl; } void Alarm() { cout << "Pass when locked, alarm!" << endl; } void ThankYou() { cout << "unlock (event:coin)-> unlock" << endl; } }; //具体状态类的实现,因为循环依赖的原因这里必须在Turnstile定义之后实现 void TurnstileLockedState::CoinEvent(Turnstile* pTs) { pTs->SetState(UNLOCKED);//状态切换 pTs->Unlock();//执行Action } void TurnstileLockedState::PassEvent(Turnstile* pTs) { //状态切换:空 pTs->Alarm();//执行Action } void TurnstileUnlockedState::CoinEvent(Turnstile* pTs) { //状态切换:空 pTs->ThankYou();//执行Action } void TurnstileUnlockedState::PassEvent(Turnstile* pTs) { pTs->SetState(LOCKED);//状态切换 pTs->Lock();//执行Action } int main(int argc, char** argv) { //以此Action作为Turnstile的动作 Turnstile turnstile; //运行Turnstile turnstile.SetState(LOCKED); turnstile.PassEvent(); //assert(turnstile.state == LOCKED); turnstile.CoinEvent();//to be unlocked turnstile.PassEvent();//to be locked //assert(turnstile.state == LOCKED); } #endif