在什么情况下我们应该采用国家模式

In what situation should we adopt state pattern?

本文关键字:国家 模式 情况下 我们 在什么      更新时间:2023-10-16

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

我被指派维护一个项目,项目状态机是由2000多行长的交换机实现的。扩展函数会很困难,所以我想重构它。我正在调查国家设计模式,但我有一些困惑。

一个简单的例子:

1.初始状态"WAIT",等待用户发送下载命令

2.当用户发送下载命令时,移动到"CONNECT"状态,连接到服务器

3.创建连接后,转到"下载"状态,保持从服务器接收数据

4.当数据下载完成时,转到"断开连接",断开与服务器的链接

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

一种简单的状态机pic

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

    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
        }
    };
    

我想知道在这种情况下,状态模式是否比函数指针更棒。。。只使用函数指针也可以提高可读性(与开关情况相比),而且更简单。状态模式将创建多个类,并且比仅使用函数指针更复杂。使用状态模式的优点是什么?

谢谢你抽出时间!

使用状态模式的优点是什么?

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

也就是说,这种模式本身有几个优点:

  1. 它限制了程序可以处于的状态的数量,从而消除了未定义的状态
  2. 它允许通过添加新状态而不是重构整个代码来更容易地扩展应用程序
  3. 从公司的角度来看,这是安全的,即使多人在同一个班上工作

由于您将该问题标记为与c++相关,因此最好考虑到该语言的给出和要求。虽然classes提供了继承,但大量的类可以大大增加编译时间。因此,当涉及到实现时,如果您的状态机很大,那么静态多态性可能是可行的。