有限状态机
(
英语:finite-state machine
,
缩写
:
FSM
)又称
有限状态自动机
,简称
状态机
,是表示有限个
状态
以及在这些状态之间的转移和动作等行为的
数学模型
。
就像上面说的,既然是数学模型当然有很多的实现方法。其实最简单容易想到的方法就是使用switch case的写法:
[cpp]
view plain
copy
1. swtich(case)
2. {
3. case
4. do
5. break;
6. case
7. do
8. break;
9. .......
10. }
[cpp]
view plain
copy
1. 但是这种写法会带来很多的问题,首先是当状态多的时候,switch case的语句会写的很长,使得可读性非常差。其次,可维护性也很差,每当要添加一个状态转换时,就要在Switch case添加相应的状态转换函数。会使得代码变得冗长,难以扩展。
[cpp]
view plain
copy
1. 当使用状态模式写状态机的时候,每一个状态就是一个类,添加状态只需要添加一个状态类就行了。在每一个类中实现相应的状态转换函数。
[cpp]
view plain
copy
1. 使用状态模式的好处:
[cpp]
view plain
copy
1. 1 每一个状态就是一个类,便于扩展,可读性高
[cpp]
view plain
copy
1. 2 每一个类有一个状态转换函数,使得整个代码的层次结构,很清晰
[cpp]
view plain
copy
1. 当然,没有一个东西是完美的。使用状态模式实现的时候,会使得类可能会变得很庞大。当总的来说,还是好处大于坏处的。毕竟代码不仅是出产品,还要考虑这个代码的扩展性还有可读性。一个只实现了功能,但扩展性很差,或者是除了你没有人看得懂,或者是很难看懂的代码,绝不是好代码。简单高效才是我们程序员追求的目标。
[cpp]
view plain
copy
1. 一个很简单的例子,仿照电梯的例子:
[cpp]
view plain
copy
1. <pre style="color: rgb(37, 37, 37); margin-top: 0px; margin-bottom: 0px;"><pre style="margin-top: 0px; margin-bottom: 0px;"><span style=" color:#008000;">/************************************************************************</span>
Des: 状态机,负责状态的装换************************************************************************/#include "statemachine.h"#include "StateDefine.h"using namespace std;StateMachine::StateMachine()
{
//起始的状态为停止状态m_currentState = m_lastState = STOP_STATE;
}
StateMachine::~StateMachine()
{
}
/*** @brief 状态机的初始化函数,负责把每一个状态的类放入Map中进行管理*/void StateMachine::init()
{
m_stateManager[0] = new CloseState();m_stateManager[1] = new OpenState();m_stateManager[2] = new UpState();m_stateManager[3] = new DownState();m_stateManager[4] = new StopState();(m_stateManager[4])->handle(this);
}
/*** @brief 状态装换函数,当需要切换状态的时候,只需要调用此函数* @param stateId :每一个状态都有一个相应的ID,定义在StateDefine的头文件中*/void StateMachine::changeState(int stateId)
{
if( stateId == m_currentState ){cout<<"curent state is "<<stateId<<"doesn't transfrom state"<<endl;return;}else{int temp = m_lastState;m_lastState = m_currentState;m_currentState = stateId;std::map<int,State*>::iterator it = m_stateManager.find(stateId);if( it != m_stateManager.end() ){if( !(it->second)->handle(this)){m_currentState = m_lastState;m_lastState = temp;}}}
}
/*** @brief 获得上次的状态* @return 返回状态ID*/int StateMachine::getLastState()
{
return m_lastState;
}
/*** @brief 获得当前的状态* @return 返回状态ID*/int StateMachine::getState()
{
return m_currentState;
}
然后是每一个状态的类:
/************************************************************************Des: 下落的状态/************************************************************************/#include "downstate.h"#include "StateDefine.h"#include "statemachine.h"using namespace std;DownState::DownState()
{
}
DownState::~DownState()
{
cout<<"destructor downstate"<<endl;
}
/*** @brief 处理相应的状态装换* @param 传入状态机* @return*/bool DownState::handle(StateMachine* p_machine)
{
//判断上次的状态是否能正确切换到现在的状态if( (p_machine->getLastState() != CLOSE_STATE) || (p_machine->getLastState() != STOP_STATE)){if(p_machine->getLastState() != CLOSE_STATE)cout<<"the lift must be close!"<<endl;elsecout<<"the lift must be stoped"<<endl;return false;}cout<<"the lift is downing "<<endl;return true;
}
/************************************************************************Des:关闭的状态/************************************************************************/#include "closestate.h"#include "StateDefine.h"#include "statemachine.h"using namespace std;CloseState::CloseState()
{
}
CloseState::~CloseState()
{
cout<<"destructor closestate"<<endl;
}
bool CloseState::handle(StateMachine* p_machine)
{
if( (p_machine->getLastState() != OPEN_STATE)){cout<<"the lift must be closed!"<<endl;return false;}cout<<"the lift is closing "<<endl;return true;
}
/************************************************************************* Des: 开启的状态/************************************************************************/#include "openstate.h"#include "StateDefine.h"#include "statemachine.h"using namespace std;OpenState::OpenState()
{
}
OpenState::~OpenState()
{
}
bool OpenState::handle(StateMachine* p_machine)
{
if( p_machine->getLastState() != STOP_STATE ){cout<<"the lift must be stop!"<<endl;return false;}cout<<"the lift is opening"<<endl;return true;
}
/************************************************************************* Des: 停止的状态/************************************************************************/#include "stopstate.h"#include "statemachine.h"#include "StateDefine.h"using namespace std;StopState::StopState()
{
}
StopState::~StopState()
{
}
bool StopState::handle(StateMachine* p_machine)
{
if(p_machine->getLastState() == p_machine->getState()){cout<<"the lift is stop "<<endl;return true;}if( p_machine->getLastState() == STOP_STATE ){cout<<"the lift have already be stopping!"<<endl;return false;}cout<<"the lift is stop "<<endl;return true;
}
/************************************************************************* Des: 上升的状态/************************************************************************/#include "upstate.h"#include "StateDefine.h"#include "statemachine.h"using namespace std;UpState::UpState()
{
}
UpState::~UpState()
{
cout<<"destrucotor update"<<endl;
}
bool UpState::handle(StateMachine* p_machine)
{
if( p_machine->getLastState() != CLOSE_STATE ){cout<<"the lift must be close!"<<endl;return false;}cout<<"the lift is uping"<<endl;return true;
}
下面是公共的头文件,定义了每一个状态对应的枚举值,方便管理
/************************************************************************* Des: 定义一个枚举,每一个状态对于一个值/************************************************************************/#ifndef STATEDEFINE_H#define STATEDEFINE_Henum{CLOSE_STATE,OPEN_STATE,UP_STATE,DOWN_STATE,STOP_STATE,
};
#endif // STATEDEFINE_H
下面是每一个状态的父类,使用了虚函数,使得对外的切换状态的接口是统一的
/************************************************************************* Des: 每一个状态的父类,定义了虚函数(handle),每一个状态都实现了这个函数,* 实现状态的切换具体实现,多态的体现/************************************************************************/#ifndef STATE_H#define STATE_Hclass StateMachine;class State
{
public:State();virtual ~State();virtual bool handle(StateMachine* p_machine) = 0;
};
#endif // STATE_H 使用次状态模式的具体类:
/************************************************************************* Des: 电梯的具体类,负责实现电梯的具体逻辑/************************************************************************/#include "lift.h"#include <iostream>#include "StateDefine.h"using namespace std;Lift::Lift()
{
}
Lift::~Lift()
{
delete this->m_stateMachine;this->m_stateMachine = nullptr;
}
/*** @brief 电梯的初始化,使用按键模拟电梯的行为*/void Lift::init()
{
this->m_stateMachine = new StateMachine();this->m_stateMachine->init();while (true) {cout<<"enter the value"<<endl;char str[8] = {0};cin>>str;if( !strcmp(str,"c")){this->m_stateMachine->changeState(CLOSE_STATE);}else if( !strcmp(str,"o")){this->m_stateMachine->changeState(OPEN_STATE);}else if( !strcmp(str,"u")){this->m_stateMachine->changeState(UP_STATE);}else if( !strcmp(str,"d")){this->m_stateMachine->changeState(DOWN_STATE);}else if( !strcmp(str,"s")){this->m_stateMachine->changeState(STOP_STATE);}}
}
使用状态模式确实使得使用避免过度的使用了IF ELSE 或者是Switch case,也使得整个的逻辑变得清晰可见。初探状态模式,还有些不足,以后改进!!(_~ ~_)
[cpp]
view plain
copy
1. <pre style="margin-top: 0px; margin-bottom: 0px;">
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
基于C++有限状态机的实现技术
一.引言言有限状态机是一种用来进行对象行为建模的工具,其作用主要是描
sed 状态机 有限状态机 -
java有限状态机实现 有限状态机 编译原理
编译原理正则文本与有限状态机
javascript 有限状态机 内功 初始状态 标识符 字符串