摘要:使用层次状态机向导(UML StateWizard), 在通用集成开发环境中VC++中,为嵌入式系统/Win32/WinCE应用构造有限状态机。
1 引言
层次状态机(Hierarchy State Machine)是实现状态建模的一种很好的形式方法。状态图是层次结构的,也就是说每个状态可以拥有子状态。这个主意很简单,效果却异常强大。 从人类思维的角度来看,平面状态模型无法进行扩展。当状态和转换的数量增长时,平面模型就会变得难于理解。而层次状态模型则可以分部分考察,每一部分理解起来相对就变得简单了。
当UML(Unified Modeling Language)首先被采用时,许多开发者把UML技术合并到静态的CASE(Computer Aided Software Engineering)技术中去,用它们来可视化的构建软件体系结构。其中最著名的采用了UML方法的CASE工具就是Rational Rose。但是它独立于通用的集成开发环境,且软件庞大费用高昂。
我们认为一UML工具必须具有以下几个特点:
· 支持UML图的生成;
· 支持正向工程,能代码生成, 不仅能支持代码生成;
· 支持反向工程,能根据代码,解析对象之间关系,创建UML图;
· 支持往返工程, 任何一程序从设计到编程到测试,不可能不经过修改,一个好的工具应该能允许开发者修改代码,并让设计能及时更新;
· 支持文挡化,能把设计和实现保存成文挡。
很多UML工具能支持正向工程,例如(Finite State Machine Editor)。但能支持往返工程的比较少。StateWizard类似于ClassWizard,运行于VC++,提供一层次状态机的框架,支持状态树,状态图的生成,支持往返工程。
2 什么是层次状态机
层次状态机(Hierarchy State Machine)是对状态行为建模的最直观的方法,也是实现事件驱动系统的一种很好的形式方法。主要用来描述对象、子系统、系统的生命周期。通过层次状态机可以了解到一个对象能到达的所有状态以及对象收到的事件对对象状态的影响等。状态机指定对象的行为以及不同状态行为的差异。同时,它还能说明事件是如何改变一个对象的状态。因此非常适用于软件开发。为便于理解,下面给出HSM 中的相关概念。
① 状态:状态是对象的生命周期中满足某种条件,执行某些动作或等待某些事件发生的一个阶段。
② 事件:事件是一个在时空中显示出现的特定现象,它可以触发状态转换。
③ 转换:转换是从一个状态结点到另一个状态结点的移动。
层次状态机较之经典的状态机,最重要的改进就是引入了层次式状态。状态层次嵌套的主要特性来自抽象与层次的结合。这是一种降低复杂性的传统途径,也就是软件中的继承。在面向对象中,类继承概念描述了类和对象之间的关系。类继承描述在类中的is-a 关系。在嵌套状态中,只需用is-in状态关系代替is-a类关系,即它们是等同的分类法。状态嵌套允许子状态继承来自其超状态的状态行为,因此它被称为行为继承。
图一:层次状态机
3 状态机框架
应用框架是指一个可复用的、部分实现的软件制品,能够被实例化扩展,以生成特定的应用。它是一个不完全的系统,是一个特定领域内的应用程序的部分设计和实现。它能够被裁剪,从而创造一个完整的应用程序。典型的应用程序框架有:Microsoft Foundation Class(MFC), 它为C++用户提供一套面向对象程序开发的辅助工具,称之为类向导器(Class Wizard);Delphi和Visual Basic,被称之为一种程序快速开发工具,它们采用属性、方法、事件结构,是一种基于组件的开发应用框架。
我们定义了一系列特殊的宏作为状态机的映射数据。这些宏映射到状态枚举、事件处理函数声明、状态的事件处理函数表、状态树定义和应用程序变量定义。具体如下定义如下:
状态枚举:
#define SME_BEGIN_STATE_DECLARE(_app) enum _app##_state_enum_t \
{#define SME_STATE_DECLARE(_state) _state, #define SME_MAX_STATE(_app)\
_app##_max_state #define SME_END_STATE_DECLARE };
状态事件处理函数表定义:
#define SME_ENTRY_FUNC_IDX 0
#define SME_EXIT_FUNC_IDX 1
#define SME_EVENT_HANDLER_FUNC_IDX 2
#define SME_BEGIN_STATE_DEF(_app,_state) \
static const SME_EVENT_TABLE_T _app##_state##_event_hdl_tbl[]= \
{#define SME_STATE_ENTRY_FUNC( _EntryFunc) \
{ SME_INVALID_EVENT_ID, _EntryFunc, 0},
#define SME_STATE_EXIT_FUNC( _ExitFunc) \
{ SME_INVALID_EVENT_ID, _ExitFunc, 0},
#define SME_ON_EVENT(_EventID, _Handler, _NewState) \
{ _EventID, _Handler, _NewState},
#define SME_END_STATE_DEF { SME_INVALID_EVENT_ID, 0, SME_INVALID_STATE}
};
状态树定义:
#define SME_BEGIN_STATE_TREE_DEF(_app) \
extern const SME_STATE_TREE_TABLE_T _app##_state_tree[] = \
{#define SME_STATE(_app,_state,_state_parent,_def_substate) \
{(SME_EVENT_TABLE_T*)_app##_state##_event_hdl_tbl, \
_state,_state_parent,_def_substate},\
#define SME_END_STATE_TREE_DEF };
应用程序定义:
#define SME_APPLICATION_DEF(_app,_app_name) \
struct SME_APP_T _app##App = { \
_app_name, NULL, NULL, 0, NULL, NULL, _app##_state_tree, SME_INVALID_STATE};
#define SME_GET_APP_VAR(_app) _app##App
#define SME_DEC_EXT_APP_VAR(_app) extern SME_APP_T _app##App;
根据这些定义,状态机向导生成如下代码,它构造了RecorderApp状态机。对应于状态图,如图二所示,可生成相对应的状态树。
SME_BEGIN_STATE_DECLARE(RecorderApp)
/*{{SME_STATE_DECLARE(RecorderApp)*/
SME_STATE_DECLARE(RecorderApp)
SME_STATE_DECLARE(Off)
SME_STATE_DECLARE(On)
SME_STATE_DECLARE(Stop)
SME_STATE_DECLARE(Play)
SME_STATE_DECLARE(Record)
SME_MAX_STATE(RecorderApp)
/*}}SME_STATE_DECLARE*/
SME_END_STATE_DECLARE
SME_BEGIN_STATE_DEF(RecorderApp,RecorderApp)
/*{{SME_STATE_DEF(RecorderApp,RecorderApp)*/
SME_STATE_ENTRY_FUNC(NULL)
SME_STATE_EXIT_FUNC(NULL)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(RecorderApp,Off)
/*{{SME_STATE_DEF(RecorderApp,Off)*/
SME_STATE_ENTRY_FUNC(NULL)
SME_STATE_EXIT_FUNC(NULL)
SME_ON_EVENT(EVENT_POWER,NULL,On)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(RecorderApp,On)
/*{{SME_STATE_DEF(RecorderApp,On)*/
SME_STATE_ENTRY_FUNC(NULL)
SME_STATE_EXIT_FUNC(NULL)
SME_ON_EVENT(EVENT_POWER,OnOnEVENT_POWER,Off)
SME_ON_EVENT(EVENT_STOP,OnOnEVENT_STOP,Stop)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(RecorderApp,Stop)
/*{{SME_STATE_DEF(RecorderApp,Stop)*/
SME_STATE_ENTRY_FUNC(StopEntry)
SME_STATE_EXIT_FUNC(StopExit)
SME_ON_EVENT(EVENT_PLAY,OnStopEVENT_PLAY,Play)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(RecorderApp,Play)
/*{{SME_STATE_DEF(RecorderApp,Play)*/
SME_STATE_ENTRY_FUNC(PlayEntry)
SME_STATE_EXIT_FUNC(PlayExit)
SME_ON_EVENT(EVENT_RECORD,OnPlayEVENT_RECORD,Record)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(RecorderApp,Record)
/*{{SME_STATE_DEF(RecorderApp,Record)*/
SME_STATE_ENTRY_FUNC(RecordEntry)
SME_STATE_EXIT_FUNC(RecordExit)
/*}}SME_STATE_DEF*/
SME_END_STATE_DEF
/*{{SME_STATE_STATETREE_SEPARATOR}}*/
SME_BEGIN_STATE_TREE_DEF(RecorderApp)
/*{{SME_STATE_TREE_DEF(RecorderApp)*/
SME_STATE(RecorderApp,RecorderApp,SME_INVALID_STATE,Off)
SME_STATE(RecorderApp,Off,0,-1)
SME_STATE(RecorderApp,On,0,Stop)
SME_STATE(RecorderApp,Stop,On,-1)
SME_STATE(RecorderApp,Play,On,-1)
SME_STATE(RecorderApp,Record,On,-1)
/*}}SME_STATE_TREE_DEF*/
SME_END_STATE_TREE_DEF
/*{{SME_DEC_IMP_SEPARATOR}}*/
SME_APPLICATION_DEF(RecorderApp, "RecorderApp")
图二:状态树