状态机我们大家都知道,有一个专门的设计模式状态机模式,类图大概如下图:不过如果按照下面图来实现的状态机,基本来说非常难用,没有实用性,只能作为教科书的产品。今天我们要实现的是一种通用状态机,可以Send事件,每一个状态可以响应自己注册的事件,同时也可以通过自身或者事件来改变状态机的状态
代码地址:https://github.com/9435202/StateAPI
首先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] 返回state
State* 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);
// 递归send
void 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_
contex.cpp
#include "Context.h"
#include "State.h"
namesp