一个简单的电梯状态模型

原创 2012年03月23日 21:28:05

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


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

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模式实现方式,则需要先枚举事件,然后再调用状态机的相应事件响应函数。各有特点。



设计模式-状态模式State-电梯状态

1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理。最直接的解决方案是将这些所有可能发生的情况全都考虑到。然后使用if... ellse语句来做状态判断来进行不同情况的处理。...

电梯系统OO设计

理论上应该先黑盒用例,分析需要求,系统边界的输入输出,再白盒类图。 但是对于现实世界模拟的OO,个人感觉先emulate现实世界,初步识别类和类之间的关系,再用用例和顺序图丰富、修正类图。 识别类,最...
  • binling
  • binling
  • 2015年09月17日 17:43
  • 1709

Qt状态机框架的一个典型模型

  • 2012年02月04日 09:30
  • 15KB
  • 下载

一个简单的java socket模型

  • 2013年03月30日 03:15
  • 6KB
  • 下载

java 多线程 模拟一台电梯的工作状态

package 电梯03; /* 单线程电梯(1台电梯运行,10层)模拟: * Stack 表示电梯所能装载的人数 * 下面两个链表表示每层楼对应的人 0未启用 * LinkList[] ...
  • Sun_Ru
  • Sun_Ru
  • 2016年08月14日 16:41
  • 1279

VRML一个简单模型显示器的制作

  • 2014年12月11日 16:01
  • 448B
  • 下载

一个简单的OpenGL多线程渲染模型

  • 2015年01月22日 16:17
  • 458KB
  • 下载

java 多线程协作 模拟四台电梯的工作状态并统计每层上下楼人数和输出上下楼日志到文件

模拟四台电梯的工作状态 package 电梯03; /* 单线程电梯(1台电梯运行,10层)模拟: * Stack 表示电梯所能装载的人数 * 下面两个链表表示每层楼对应的人 0未启用 ...
  • Sun_Ru
  • Sun_Ru
  • 2016年08月16日 23:39
  • 1169

用犀牛简单建的一个模型

  • 2015年06月17日 22:02
  • 1.78MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一个简单的电梯状态模型
举报原因:
原因补充:

(最多只允许输入30个字)