有限状态机通常用来描述一个对象在其生命周期中的状态变化,以及对外界的刺激(条件改变)做出响应进而进入下一个状态,最经典就是TCP状态转移。

这里要实现的是一种通用状态机,可以Send事件,每一个状态可以响应自己注册的事件,同时也可以通过自身或者事件来改变状态机的状态。
Contex类:CreateState() 接口,用于创建状态机和父状态机关系Update() 接口,外部驱动状态机函数SendEvent() 同步发送事件到当前状态,能发送任意数据到状态中处理SendAsyncEvent() 异步发送事件到当前状态,能发送任意数据到状态中处理State类virtual void start(){} // 状态开始处理 子类实现virtual void update(){} // update处理 子类实现virtual void stop(){} // 状态结束处理 子类实现void set_event_func(); // 设置事件处理回调函数,子类绑定
框架
context.h
#ifndef _CONTEXT_H_#define _CONTEXT_H_#include "Event.h"#include <string>#include <unordered_map>#include <thread>namespace HsmState{class State;struct NodeState{NodeState& operator = (const NodeState& n){_state = n._state;_father_name = n._father_name;return *this;}State* _state;std::string _father_name;};class Context{public:friend class State;Context();~Context();// 开始状态机bool Start(std::string name);// 创建一个状态// [in] state 状态对象,在Context销毁时,内部释放state// [in] name 状态名称,为空名称为typedname的值// [in] father_name 父状态的名称// [out] 返回stateState* CreateState(State* state, std::string name, std::string father_name = "");// 更新当前状态void Update();// 同步事件// 发送一个事件,提供给root状态和当前状态处理// 如果当前状态是子状态,则还会给父状态处理void SendEvent(EventData event_data);// 异步事件void SendAsyncEvent(EventData event_data);// 获取当前状态名称std::string GetCurStateName();private:// 状态切换void TransForState(std::string name);// 递归sendvoid RecursiveSend(NodeState& node_state, EventData& event_data);std::unordered_map<std::string, NodeState> _states; // 状态列表NodeState _cur_node_state; // 当前状态名std::string _cur_name;std::string _root_name; // 根状态名};}#endif // !STATE_H_
context.cpp
#include "Context.h"#include "State.h"namespace HsmState{Context::Context(){}Context::~Context(){for (auto iter : _states){if (iter.second._state){delete iter.second._state;iter.second._state = nullptr;}}_states.clear();}// 开始状态机bool Context::Start(std::string name){std::unordered_map<std::string, NodeState>::iterator iter_map = _states.find(name);if (iter_map != _states.end()){_cur_node_state = iter_map->second;_cur_name = iter_map->first;iter_map->second._state->start();}return false;}// 创建一个状态// [in] state 状态对象,在Context销毁时,内部释放state// [in] name 状态名称,为空名称为typedname的值// [in] father_name 父状态的名称// [out] 返回stateState* Context::CreateState(State* state, std::string name, std::string father_name){NodeState node_state;node_state._state = state;node_state._state->SetContext(this);node_state._father_name = father_name;_states[name] = node_state;return state;}// 更新当前状态void Context::Update(){_cur_node_state._state->update();}// 同步事件// 发送一个事件,提供给root状态和当前状态处理// 如果当前状态是子状态,则还会给父状态处理void Context::SendEvent(EventData event_data){RecursiveSend(_cur_node_state, event_data);}// 异步事件void Context::SendAsyncEvent(EventData event_data){// todo 待实现}std::string Context::GetCurStateName(){return _cur_name;}// 递归sendvoid Context::RecursiveSend(NodeState& node_state, EventData& event_data){EventDeal event_deal = node_state._state->RunEventFunc(event_data);if (event_deal == keep_on&& !node_state._father_name.empty()){std::unordered_map<std::string, NodeState>::iterator iter_map = _states.find(node_state._father_name);if (iter_map != _states.end()){RecursiveSend(iter_map->second, event_data);}}}void Context::TransForState(std::string name){std::string str_name = std::string(name);std::unordered_map<std::string, NodeState>::iterator iter_map = _states.find(str_name);if (iter_map != _states.end()){// 停止上一个状态_cur_node_state._state->stop();// 初始化下一个状态_cur_node_state = iter_map->second;_cur_name = iter_map->first;_cur_node_state._state->start();}}}
state.h
#ifndef _STATE_H_#define _STATE_H_#include "Event.h"#include<functional>#include<string>namespace HsmState{class Context;class State{public:// 进入状态时调用,子类重写virtual void start(){}// 更新状态,可以由外部周期性调用virtual void update(){}// 停止状态是调用,子类重写virtual void stop(){}// 设置事件响应回调函数void set_event_func(std::function<EventDeal(EventData&)> func);EventDeal RunEventFunc(EventData& event_data);void SetContext(Context* context);// 切换状态// [in] name 状态名称void TransState(std::string name);private:std::function<EventDeal(EventData&)> _event_func;Context *_context;};}#endif // !STATE_H_
state.cpp
#include "Context.h"#include "State.h"namespace HsmState{// 设置时间响应回调函数void State::set_event_func(std::function<EventDeal(EventData&)> func){_event_func = func;}EventDeal State::RunEventFunc(EventData& event_data){if (_event_func == nullptr)return keep_on;return _event_func(event_data);}void State::SetContext(Context* context){_context = context;}void State::TransState(std::string name){_context->TransForState(name);}}
event.h
#pragma oncenamespace HsmState{enum EventDeal{tail = 0, // 事件结束处理keep_on // 事件继续传递};// 事件数据class EventData{public:EventData(int event_type){_event_type = event_type;_data = nullptr;}template <class T>void SetData(T* t){_data = t;}template <class T>T* GetData(){return (T*)_data;}int _event_type;private:void* _data;};}
应用举例
假如一个人一天生活状态变化:
    
则OneDayState.cpp
#include "Context.h"#include "State.h"#include <thread>#include <chrono>#include <iostream>#include <functional>using namespace HsmState;bool run = true;enum EventS{belazy = 0, // 偷懒事件};// 开始状态class StartState : public State{public :void start(){std::cout << "StartState start" << std::endl;}void stop(){std::cout << "StartState stop" << std::endl;}void update(){time++;if (time == 10){TransState("HungerState");}}int time = 0;};// 饥饿状态class HungerState : public State{public:void start(){std::cout << "HungerState start" << std::endl;}void stop(){std::cout << "HungerState stop" << std::endl;}void update(){time++;if (time == 10){TransState("Dinner");}}int time = 0;};class Dinner : public State{public:void start(){std::cout << "Dinner start" << std::endl;}void stop(){std::cout << "Dinner stop" << std::endl;}void update(){TransState("DoTheCookingState");}};// 做饭状态class DoTheCookingState : public State{public:void start(){std::cout << "DoTheCookingState start" << std::endl;}void stop(){std::cout << "DoTheCookingState stop" << std::endl;}void update(){time++;if (time == 60){TransState("EatState");}}int time = 0;};// 吃饭状态class EatState : public State{public:void start(){std::cout << "EatState start" << std::endl;}void stop(){std::cout << "EatState stop" << std::endl;}void update(){time++;if (time == 5){TransState("SleepState");}}int time = 0;};// 饭后睡觉状态class SleepState : public State{public:void start(){std::cout << "SleepState start" << std::endl;}void stop(){std::cout << "SleepState stop" << std::endl;}void update(){time++;if (time == 30){TransState("WorkState");}}int time = 0;};// 工作状态class WorkState : public State{public:void start(){std::cout << "WorkState start" << std::endl;std::function<EventDeal(EventData&)> func = std::bind(&WorkState::DealEvent, this, std::placeholders::_1);;set_event_func(func);}void stop(){std::cout << "WorkState stop" << std::endl;}EventDeal DealEvent(EventData &event_data){switch ((EventS)event_data._event_type){case belazy:TransState("LoafOnAJob");break;default:break;}return keep_on;}void update(){time++;if (time == 180){run = false;}}int time = 0;};// 工作摸鱼状态class LoafOnAJob : public State{public:void start(){time = 0;std::cout << "LoafOnAJob start" << std::endl;}void stop(){std::cout << "LoafOnAJob stop" << std::endl;}void update(){time++;if (time == 10){TransState("WorkState");}}int time = 0;};// 对象工厂class Factory{public :static State* CreateState(Context* context, std::string name, std::string parent_name = ""){State* state = nullptr;if (name == "StartState"){state = new StartState();}else if (name == "HungerState"){state = new HungerState();}else if (name == "Dinner"){state = new Dinner();}else if (name == "DoTheCookingState"){state = new DoTheCookingState();}else if (name == "EatState"){state = new EatState();}else if (name == "SleepState"){state = new SleepState();}else if (name == "WorkState"){state = new WorkState();}else if (name == "LoafOnAJob"){state = new LoafOnAJob();}context->CreateState(state, name, parent_name);return state;}};int main(){Context* context = new Context();// 创建状态机Factory::CreateState(context, "StartState");Factory::CreateState(context, "HungerState");Factory::CreateState(context, "Dinner");Factory::CreateState(context, "DoTheCookingState", "Dinner");Factory::CreateState(context, "EatState", "Dinner");Factory::CreateState(context, "SleepState");Factory::CreateState(context, "WorkState");Factory::CreateState(context, "LoafOnAJob");// 开始状态机context->Start("StartState");int time = 0;while (run){time++;std::this_thread::sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::milliseconds(10)));context->Update();// 如果为工作状态,每隔60分钟发出偷懒事件if (context->GetCurStateName() == "WorkState"&& time % 60 == 0){EventData e = EventData((int)belazy);context->SendEvent(e);}}if (context){delete context;context = nullptr;}std::cout << "state close" << std::endl;return 0;}

