在什么情况下我们应该采用州模式?

时间:2015-11-19 13:02:20

标签: c++ design-patterns state-machine

在什么情况下我们应该采用州模式?

我被分配到维护一个项目,项目状态机由switch-case实现,长度超过2000行。扩展功能很难,所以我想重构一下。 我正在调查州的设计模式,但我有一些困惑。

一个简单的例子:

1。初始状态“WAIT”,等待用户发送下载命令

2。用户发送下载命令时,移至“CONNECT”状态,连接服务器

3。创建连接后,转到“DOWNLOADING”状态,保持从服务器接收数据

4。数据下载完成后,移至“DISCONNECT”,断开与服务器的链接

5。断开连接后,进入“WAIT”状态,等待用户发送下载命令

A simple state machine pic

  • 方法1:在我调查状态模式之前,我认为一个简单的方法---在不同的函数中包装不同的状态行为,使用函数指针数组指向每个状态函数,并通过调用函数改变状态。 / p>

    typedef enum {
        WAIT,
        CONNECT,
        DOWNLOADING,
        DISCONNECT
    }state;
    void (*statefunction[MAX_STATE])(void) = 
    {
        WAITState,
        CONNECTState,
        DOWNLOADINGState,
        DISCONNECTState
    };
    void WAITState(void)
    {
        //do wait behavior
        //while receive download command
        //statefunction[CONNECT]();
    }
    void CONNECTState(void)
    {
        //do connect behavior
        //while connect complete
        //statefunction[DOWNLOADING]();
    }
    void DOWNLOADINGState(void)
    {
        //do downloading behavior
        //while download complete
        //statefunction[DISCONNECT]();
    }
    void DISCONNECTState(void)
    {
        //do disconnect behavior
        //while disconnect complete
        //statefunction[WAIT]();
    }
    
  • 方法2:状态模式在不同的类(面向对象的状态机)中封装不同的状态及其行为,使用多态实现不同的状态行为,并为所有具体状态定义一个公共接口。

    class State
    {
    public:
         virtual void Handle(Context *pContext) = 0;
    };
    class Context
    {
    public:
        Context(State *pState) : m_pState(pState){}
    
        void Request()
        {
            if (m_pState)
            {             
                m_pState->Handle(this);           
            }
         }   
    private:
        State *m_pState;
    };
    class WAIT : public State
    {
    public:
        virtual void Handle(Context *pContext)
        {
            //do wait behavior
        }
    };
    class CONNECT : public State
    {
    public:
        virtual void Handle(Context *pContext)
        {
            //do connect behavior
        }
    };
    class DOWNLOADING : public State
    {
    public:
        virtual void Handle(Context *pContext)
        {
            //do downloading behavior
        }
    };
    class DISCONNECT : public State
    {
    public:
        virtual void Handle(Context *pContext)
        {
            //do disconnect behavior
        }
    };
    

我想知道状态模式是否比这种情况下的函数指针要好... 仅使用函数指针也可以提高可读性(与switch-case相比),而且更简单。 状态模式将创建几个类,并且比仅使用函数指针更复杂。 使用状态模式有什么好处?

谢谢你的时间!

1 个答案:

答案 0 :(得分:0)

  

使用状态模式有什么好处?

首先,需要注意的是,两个你提供的方法, 实际上是相同模式的例子 。其中一种方法描述了基于函数的实现,而另一种方法更多地采用了面向对象的方法。

话虽这么说,模式本身有一些优点:

  1. 它限制了一个程序可以进入的状态数,从而消除了未定义的状态,
  2. 通过添加新状态,而不是重构整个代码,可以更轻松地扩展应用程序,
  3. 从公司的角度来看,它是安全的,即使多人在同一个班级工作,
  4. 由于您将问题标记为与相关,因此最好考虑语言提供和要求的内容。虽然classes提供继承,但是大量的类可以大大增加编译时间。因此,当涉及到实现时,如果您的状态机static polymorphism可能是最佳选择。