最近的状态极差,甚至代码也写不下去了。给自己手臂上的两刀没有任何的作用,看来早已经是麻痹了。
一直想弄一个勉强能用的状态机,用于在各种涉及到状态转换的时候用到,然而脑子并不是太清醒。
先放在这里一个接口,以后会用到的。
状态机主要由3部分组成: 状态,输入,转换。可以在Input中实现状态机的转换蓝图;“状态”可以用枚举来表示。每当存在一个新的状态,那么就需要继承一次下面的接口。
其中的StateStack可以用来做下推自动机,这样可以在状态更新之后,用来还原之前的状态。
如果一个对象拥有多个状态,那么就要用到并发状态机。这个原理大概是,这个对象的成员中存在两个StateBase的子类对象。两者既不相互干扰还能做到同时更新。
UpdateBegin 和 UpdateEnd用来定义状态进出时的行为。但我总觉得,将它放在Input函数中而不是Update函数中更为合适。
C++14的代码,VS2017。
1 #pragma once 2 #include <chrono> 3 #include <stack> 4 5 #define GetTimeNowMicroSec \ 6 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() 7 8 template<typename TState, typename TIn, typename TTarget> 9 class StateBase 10 { 11 private: 12 StateBase(); 13 14 public: 15 typename std::stack<StateBase<TState, TIn, TTarget>*> StateStack; //Pushdown Automation 16 17 StateBase(TState st); 18 virtual ~StateBase(); 19 20 public: 21 const TState& GetStateType() const; 22 23 public: 24 virtual void Input(TTarget& tag, TIn& input) = 0; 25 virtual void Updating(TTarget& tag) = 0; 26 27 virtual void UpdateBegin(TTarget& tag); 28 virtual void UpdateEnd(TTarget& tag); 29 virtual void Update(TTarget& tag); 30 31 template<class ST, 32 typename std::enable_if < 33 std::is_base_of<StateBase, ST>::value, ST 34 > ::type * = nullptr >> 35 virtual bool operator==(const ST& left, const ST& right) const 36 { 37 return left._st == right._st; 38 } 39 40 private: 41 TState _st; 42 time_t _time; //micro 43 }; 44 45 template<typename TState, typename TIn, typename TTarget> 46 inline StateBase<TState, TIn, TTarget>::~StateBase() 47 { 48 _time = 0; 49 } 50 51 template<typename TState, typename TIn, typename TTarget> 52 inline StateBase<TState, TIn, TTarget>::StateBase(TState st): 53 _st(st) 54 { 55 } 56 57 template<typename TState, typename TIn, typename TTarget> 58 inline const TState & StateBase<TState, TIn, TTarget>::GetStateType() const 59 { 60 return _st; 61 } 62 63 template<typename TState, typename TIn, typename TTarget> 64 inline void StateBase<TState, TIn, TTarget>::UpdateBegin(TTarget & tag) 65 { 66 _time = GetTimeNowMicroSec; 67 } 68 69 template<typename TState, typename TIn, typename TTarget> 70 inline void StateBase<TState, TIn, TTarget>::UpdateEnd(TTarget & tag) 71 { 72 _time = GetTimeNowMicroSec - _time; 73 } 74 75 template<typename TState, typename TIn, typename TTarget> 76 inline void StateBase<TState, TIn, TTarget>::Update(TTarget & tag) 77 { 78 UpdateBegin(tag); 79 Updating(tag); 80 UpdateEnd(tag); 81 }