State模式(状态模式)学习

通过简单的十字专门的状态机,一步步从简单设计到运用设计原则和设计模式的实现。代码一步步抽象/重构,注释中详细说明了每一步抽象和重构的意义。代码可以拷贝编译完整运行。

#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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值