状态和存储类都介绍完了,我们就剩下调度状态变化的状态机类和复合状态类。其实从某种程度上说,复合状态是一种简单的状态机,它们在很多地方存在共性。我们从状态机类入口,进行讲解。首先看下上一文中的例子
class CMachine_Download_Run_App :
public AutoStateChart::CAutoStateChartMachine
状态机类需要继承于CAutoStateChartMachine模板类,该类声明如下:
template我们先看下这个类的成员变量。m_strCurrentState保存了状态机在跳转中的当前状态,m_strCondition保存了状态机中当前状态之前的状态的输出,它用于决定状态跳转方向。m_MapCompositeStatesSubState用于保存状态机中离开复合状态时的最后状态,即它记录复合状态机的浅历史。m_spStore指向“数据库”类对象。class CAutoStateChartMachine: public boost::enable_shared_from_this >, public CLocalStoreAccess { public: typedef LocalStore SelfStore; typedef T Self; public: CAutoStateChartMachine(){m_spStore.reset();}; virtual ~CAutoStateChartMachine(){}; private: virtual bool Transition(){return false;}; public: void StartMachine() { if ( !m_spStore ) { m_spStore = boost::make_shared >(); m_spStore->Init(); SetStore( m_spStore->m_pFunc ); } while( Transition()){}; }; private: void Init(){}; public: bool IsCompositeStates(){return false;}; protected: std::string m_strCurrentState; std::string m_strCondition; MapString m_MapCompositeStatesSubState; boost::shared_ptr > m_spStore; };
该模板类最重要的函数就是StartMachine,它在第一次被调用时创建了“数据库”类对象。然后死循环调用Transition方法。Tansition方法是个虚方法,它是整个模型的核心。状态机类需要实现自己的Transition方法,以使得状态机可以运转起来。
我们再看下复合状态类的基础模板
template因为复合状态也是一种状态,所以它也要有Entry和Exit两种方法。而其Entry方法就是调用Transition方法。该模板类的Transition方法也是虚方法,这意味着继承于该模板类的方法也要去实现Transition。class CCompositeStates: public CAutoStateChartBase { BOOST_TYPEOF_REGISTER_TYPE(T) public: CCompositeStates(){}; ~CCompositeStates(){}; private: virtual bool Transition(){return false;}; public: virtual void Entry(){while(Transition());}; virtual std::string Exit(){return m_strCondition;}; public: std::string GetCurrentState(){return m_strCurrentState;}; bool IsCompositeStates(){return true;}; void SetInitState( const std::string& strState ){ m_strCurrentState = strState; }; protected: std::string m_strCurrentState; std::string m_strCondition; MapString m_MapCompositeStatesSubState; };
于是所有的重心都集中于Transition方法的实现。
为了让代码美观,我参考了MFC中使用宏简洁代码的思路,设计了如下的宏:
#define STARTSTATE(state) \
do { \
boost::shared_ptr
sp = boost::make_shared
(); \ sp->SetStore( m_pFunc ); \ if ( sp->IsCompositeStates() ) { \ std::string strState = typeid(state).name(); \ BOOST_AUTO(it, m_MapCompositeStatesSubState.find(strState)); \ if ( m_MapCompositeStatesSubState.end() != it ) { \ sp->SetInitState(it->second); \ if ( DEBUGFRAMEFLAG ) { \ std::string strInitState = it->second; \ std::cout<<"CompositeStates SetInitState:"<
Entry(); \ m_strCondition = sp->Exit(); \ if ( sp->IsCompositeStates() ) { \ std::string strState = typeid(state).name(); \ std::string strInnerState = sp->GetCurrentState(); \ m_MapCompositeStatesSubState[strState] = strInnerState; \ if ( DEBUGFRAMEFLAG ) { \ std::cout<<"CompositeStates SaveState:"<
然后复合状态类和状态机类只要使用这些宏去组织状态跳转,就可以清晰的描述过程了。