什么是状态机
状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。英文名字叫State Machine ,不是指一台实际机器,一般就是指一张状态转换图。全称是有限状态自动机,自动两个字包含重要含义。给定一个状态机,同时给定它的当前状态以及输入,那么输出状态时可以明确的运算出来的,当输入条件时,能输出下一个状态。
现实事物是有不同状态,例如一个LED等,就有 亮 和 灭两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有限个,例如LED灯的状态就是两个亮和 灭。
为什么用状态机
状态机解决的问题就是当某种模型的状态变更比较比较复杂,且状态比较多,那么我们有必要将这些状态变化的逻辑抽象出来,做成一个可以统一调用的算法,这样封装出来的代码就比较好维护,同时可读性也很强。
状态机在实际工作开发中很有用,应用也非常广泛。一个健壮的状态机可以让你的程序,不论发生何种突发事件都不会突然进入一个不可预知的程序分支,可以很清晰的表达整个状态的流转。
在GUI应用程序、Web应用程序等事件驱动型的应用程序,采用状态机的思路来完成程序设计,可以简化设计流程,使程序的可读性、可维护性都得到增加。
使用状态机有哪些好处?
1. 当一个程序有多个状态时,规范了状态机的状态转换,避免了一些引入一些复杂的判断逻辑。
2. 规范了程序在不同状态下所能提供的能力。
3. 在能力上可以进行横向扩展,提供新的状态来完善现有逻辑。
简单状态机的实现
使用switch跳转即可实现一种简单的状态机。如果逻辑不是很复杂,使用switch语句也能达到实现目的。举例如下:
-
enum
state
-
{
-
nullState_,
-
firstState_,
-
secondState_,
-
thirdState_,
-
quitState_,
-
};
-
-
struct
param_t
-
{
-
int param1;
-
int param2;
-
// ......
-
};
-
-
int nullStateProc(param_t& param){
-
return firstState_;
-
}
-
-
int firstStateProc(param_t& param){
-
return secondState_;
-
}
-
-
int secondStateProc(param_t& param){
-
return secondState_;
-
}
-
-
int thirdStateProc(param_t& param){
-
return secondState_;
-
}
-
-
int quitEvent(){
-
return nullState_;
-
}
-
-
int stateMachine(state& state_, param_t& param){
-
switch (state_)
-
{
-
case nullState_:
-
state_ =
static_cast<state>(
nullStateProc(param));
-
break;
-
case firstState_:
-
state_ =
static_cast<state>(
firstStateProc(param));
-
break;
-
case secondState_:
-
state_ =
static_cast<state>(
secondStateProc(param));
-
break;
-
case thirdState_:
-
state_ =
static_cast<state>(
thirdStateProc(param));
-
break;
-
case quitState_:
-
quitEvent();
-
return
0;
-
}
-
-
return
1;
-
-
}
-
-
void start()
-
{
-
state state_ = nullState_;
-
param_t param{};
-
-
while (
true)
-
{
-
auto stateResult =
stateMachine(state_, param);
-
if (!stateResult)
-
{
-
return;
-
}
-
}
-
}
另一种简单实现
如果需要管理的状态和事件比较多,需要逻辑清晰和便于维护,使用简单的switch可能无法满足需求。这里介绍一种简单的实现,消除庞大的条件分支语句,从配置表容易看出各个状态的转换图。
-
/* statemachine.h*/
-
-
#ifndef _STATEMACHINE_H_
-
#define _STATEMACHINE_H_
-
-
#include <iostream>
-
-
enum
EventActionResult {
-
EventFailed, EventProcessedOK
-
};
-
-
template<
class
T,
class
P>
-
class
State {
-
public:
-
std::string inputEvent;
-
State<T, P> *nextState;
-
-
EventActionResult (T::*action)(
const std::string &event, P *param);
-
-
State<T, P> *errorState;
-
};
-
-
-
template<
class
T,
class
P>
-
class
StateMachine {
-
private:
-
State<T, P> *init;
-
State<T, P> *current;
-
T *target;
-
-
public:
-
-
StateMachine() {}
-
-
void Init(T *_target, State<T, P> *initialState) {
-
init = current = initialState;
-
target = _target;
-
}
-
-
void Reset() {
-
current = init;
-
}
-
-
void ProcessEvent(const std::string &event, P *param) {
-
for (State<T, P> *p =
this->current; p->nextState !=
NULL; p++) {
-
if (p->inputEvent == event) {
-
if (p->action !=
NULL) {
-
if (EventFailed == (
this->target->*(p->action))(event, param)) {
-
if (p->errorState !=
NULL) {
-
//Only if there's an errorstate defined. Otherwise, just do nothing
-
this->current = p->errorState;
-
}
-
return;
-
}
-
}
-
this->current = p->nextState;
-
return;
-
}
-
}
-
-
//Event not found. Do nothing
-
return;
-
}
-
};
以下是使用举例:
-
class
MyStateMachine {
-
public:
-
-
struct
param_t {
-
int param;
-
int param1;
-
int param2;
-
};
-
-
StateMachine<MyStateMachine,
param_t> stMachine;
-
-
EventActionResult HandleEvent1(const std::string &e, param_t *param);
-
-
EventActionResult HandleEvent2(const std::string &e, param_t *param);
-
-
EventActionResult HandleEventA(const std::string &e, param_t *param);
-
-
EventActionResult HandleEventB(const std::string &e, param_t *param);
-
-
EventActionResult HandleThree(const std::string &e, param_t *param);
-
-
-
void HandleEvent(const std::string &e, param_t *param);
-
-
void Init();
-
-
void Start();
-
};
-
#include "statemachine.h"
-
#include <cstdlib>
-
#include <iostream>
-
#include <stdio.h>
-
-
typedef State<MyStateMachine, MyStateMachine::
param_t> STATE;
-
-
extern STATE Idle[];
-
extern STATE One[];
-
extern STATE Two[];
-
-
-
STATE Idle[] =
-
{
-
//EVENT,NEXT, ACTION, ERRORSTATE (where to land if there's an error)
-
{
"event1", One, &MyStateMachine::HandleEvent1, Idle},
-
{
"event2", Two, &MyStateMachine::HandleEvent2, Idle},
-
{
"",
NULL,
NULL,
NULL},
//End of table
-
};
-
-
STATE One[] =
-
{
-
{
"eventA", Idle, &MyStateMachine::HandleEventA, Idle},
-
{
"eventB", Idle, &MyStateMachine::HandleEventB, Idle},
-
{
"",
NULL,
NULL,
NULL},
-
};
-
-
STATE Two[] =
-
{
-
{
"eventC", Idle,
NULL,
NULL},
-
{
"",
NULL,
NULL,
NULL},
-
};
-
-
EventActionResult MyStateMachine::HandleEvent1(const std::string &e, param_t *param) {
-
std::cout <<
"HandleEvent1,param:" << param->param << std::endl;
-
return EventProcessedOK;
-
}
-
-
EventActionResult MyStateMachine::HandleEvent2(const std::string &e, param_t *param) {
-
std::cout <<
"HandleEvent2,param:" << param->param << std::endl;
-
return EventProcessedOK;
-
}
-
-
EventActionResult MyStateMachine::HandleEventA(const std::string &e, param_t *param) {
-
std::cout <<
"HandleEventA,param:" << param->param << std::endl;
-
return EventProcessedOK;
-
}
-
-
EventActionResult MyStateMachine::HandleEventB(const std::string &e, param_t *param) {
-
std::cout <<
"HandleEventB,param:" << param->param << std::endl;
-
return EventProcessedOK;
-
}
-
-
EventActionResult MyStateMachine::HandleThree(const std::string &e, param_t *param) {
-
std::cout <<
"HandleThree" << std::endl;
-
return EventProcessedOK;
-
}
-
-
-
void MyStateMachine::HandleEvent(const std::string &e, param_t *param) {
-
stMachine.
ProcessEvent(e, param);
-
}
-
-
void MyStateMachine::Init() {
-
stMachine.
Init(
this, Idle);
-
}
-
-
void MyStateMachine::Start() {
-
while (
1) {
-
char c[
255];
-
// 模拟输入event
-
std::cin.
getline(c,
255);
-
std::string event{c};
-
MyStateMachine::
param_t param;
-
param.param =
1;
-
this->
HandleEvent(event, ¶m);
-
}
-
}
引用
什么是状态机?_pingxiaozhao的博客-CSDN博客_状态机的概念
为Linux应用构造有限状态机_wowocpp的博客-CSDN博客_linux 状态机
有限状态机详解(转载)_白小狮的博客-CSDN博客_有限状态机和无限状态机
为Linux操作系统应用构造有限状态机方法-红联Linux系统门户
一文详解 Android状态机StateMachine 使用方式及实现原理_bjxiaxueliang的博客-CSDN博客_statemachine
c++写状态机_zhi_cary的博客-CSDN博客_c++ 状态机
C++有限状态机的实现_Valreaper的博客-CSDN博客_c++ 状态机
github经典C++状态机(fsm)源代码剖析_star-keke的博客-CSDN博客
用C++来实现有限状态机(附代码)_李肖遥的博客-CSDN博客
状态模式(state)C++实现_shu_chang1993的博客-CSDN博客_c++state
c++写状态机_zhi_cary的博客-CSDN博客_c++ 状态机
转载:https://blog.csdn.net/qq8864/article/details/128204140