一个简单的电梯状态模型

来源:互联网 发布:计算机系统监控软件 编辑:程序博客网 时间:2024/05/01 01:25

题目:  "简易电梯控制系统"


大家日常生活中经见到的电梯。 你有没有想过它的内部运行机制和实现方法。现在大家就共同讨论一下电梯到底是怎么运行的。

1. 尝试画出你心目中的电梯系统架构图。大胆show出你的想法。

2. 画出电梯运行过程中的状态转换图(停止,上升,下降,开门,报警等),电梯运行的流程图。

====================================================================================================

本文主要是讨论状态机的几种实现方式, 至于电梯的状态划分是否恰当就不管了.

1      前言

本文针对电梯的运行状态转换,描述电梯的状态机模型,提供一种较高效的状态机模式的实现方式。

 

2      电梯的状态

2.1    状态转换图

 

2.2    状态列表

由上述状态图,列举状态如下:

停止状态:         StateStopping,门是关闭的

电梯上升中:     StateGoingUp

电梯下降中:     StateGoingDown

电梯开门:         StateOpened

超载报警状态:StateWarning,门是开着的

 

说明:开机即StateStopping状态。电梯停止状态包含关门状态,开门为单独一个状态。

 

2.3    事件 Event

电梯可接收的事件如下:

               ——  EVENT_UP

               ——  EVENT_DOWN

到达楼层  —— EVENT_STOP

开门           —— EVENT_OPEN

关门           —— EVENT_CLOSE

告警           —— EVENT_WARN

消除告警  —— EVENT_DELWARN

 

这些事件由硬件根据当前的机械状况产生,比如有人在某层按了按钮,硬件或控制系统会根据实际情况给电梯发上/下事件。电梯状态机负责在当前状态下处理相应事件,以便跳转到下一个新的状态,产生新的运行结果。本文只重点关注电梯本身的状态切换模型。

 

2.4    状态迁移表

 

当前状态

Event类型

转换状态

StateStopping

EVENT_OPEN

StateOpened

StateStopping

EVENT_UP

StateGoingUp

StateStopping

EVENT_DOWN

StateGoingDown

StateOpened

EVENT_CLOSE

StateStopping

StateOpened

EVENT_WARN

StateWarning

StateGoingUp

EVENT_STOP

StateStopping

StateGoingDown

EVENT_STOP

StateStopping

StateWarning

EVENT_DELWARN

StateOpened

 

3      状态机实现

3.1    表驱动方式

描述:略

优点:代码简单,适用于PPP协议等标准的状态机,只需要关心状态表即可。

缺点:状态跳转逻辑由状态表决定,不直观,无法从代码体现状态的转换。

实现:略

3.2    State模式方式

描述:State模式将处理事件的每一个分支,放入一个独立的类中,每一个事件对应派生类的一个虚函数。


优点:每个状态对应一个单独的类,将不同状态的行为分离;通过定义新的派生类,即可增加新的状态和转换。

缺点:一个状态对应一个派生类,增加了子类的数目;状态基类需要定义每个子类的虚函数,即所有状态对象要处理的消息都必须在抽象状态类中申明,增加了冗余;由于所有消息处理函数都是虚拟函数,一方面虚拟函数表占用内存,另一方面增加了调用的间接性。

实现:略。

 

3.3    成员函数指针实现方式

描述:电梯的当前状态,由一个成员函数指针保存,每个状态对应一个成员函数指针,状态的跃迁形式是成员函数指针的赋值。有事件需要处理时,委托给当前状态处理。

优点:每个状态处理的事件列举清晰,状态转换由成员函数指针赋值实现,成本低。

缺点:代码量与状态数量和事件数量相关,会随之增减。

实现

 


/** * 事件. */typedef enum tagT_EventType{    EVENT_OPEN = 0,    EVENT_UP,    EVENT_DOWN,    EVENT_CLOSE,    EVENT_WARN,    EVENT_STOP,    EVENT_DELWARN} T_EventType;

/** * 电梯实体. */class Elevator{public:    typedef void (Elevator::*T_ElevatorState)(T_EventType tEvent); //声明成员函数指针    Elevator()        :m_tNowState(&Elevator::StateStopping) //初始状态停止    {    }    /**     * 对外接口, 接收事件     */    void ProcessEvent(T_EventType tEvent)    {        (this->*(m_tNowState))(tEvent); //交给当前状态处理, 成员函数调用    }private:    void StateStopping(T_EventType tEvent);  //停止状态    void StateOpened(T_EventType tEvent);    //开门状态    void StateGoingUp(T_EventType tEvent);   //上升状态    void StateGoingDown(T_EventType tEvent); //下降状态    void StateWarning(T_EventType tEvent);   //超载状态    void SetNextState(T_ElevatorState state)    {        m_tNowState = state; //成员函数指针赋值    }    T_ElevatorState m_tNowState; /**< 当前状态. */};void Elevator::StateStopping(T_EventType tEvent){    switch (tEvent)    {    case EVENT_OPEN:        //... //通知硬件:开门        SetNextState(&Elevator::StateOpened);        break;    case EVENT_UP:        //... //通知硬件上升        SetNextState(&Elevator::StateGoingUp);        break;    case EVENT_DOWN:        //... //通知硬件:下降        SetNextState(&Elevator::StateGoingDown);        break;    default:        break;    }}void Elevator::StateOpened(T_EventType tEvent){    switch (tEvent)    {    case EVENT_CLOSE:        //... //通知硬件:关门        SetNextState(&Elevator::StateStopping);        break;    case EVENT_WARN:        //... //通知硬件超载,告警        SetNextState(&Elevator::StateWarning);        break;    default:        break;    }}void Elevator::StateGoingUp(T_EventType tEvent){    switch (tEvent)    {    case EVENT_STOP:        //... //通知硬件:到达        SetNextState(&Elevator::StateStopping);        break;    default:        break;    }}void Elevator::StateGoingDown(T_EventType tEvent){    switch (tEvent)    {    case EVENT_STOP:        //... //通知硬件到达        SetNextState(&Elevator::StateStopping);        break;    default:        break;    }}void Elevator::StateWarning(T_EventType tEvent){    switch (tEvent)    {    case EVENT_DELWARN:        //... //通知硬件删除告警        SetNextState(&Elevator::StateOpened);        break;    default:        break;    }}


/** * 控制器, 提供电梯实体和外部系统的接口. */class Controller{public:    void ProcessEvent(T_EventType tEvent)    {        m_tElevator.ProcessEvent(tEvent);    }    private:    Elevator m_tElevator; /**< 电梯实体. */};

成员函数指针这种实现方式,把对事件的枚举,放在每种状态中;而State模式实现方式,则需要先枚举事件,然后再调用状态机的相应事件响应函数。各有特点。



原创粉丝点击