赞
踩
参考博客:
(1)FSM(有限状态机)
(2)关于有限状态机(FSM)的一些思考
(3)状态设计模式
有限状态机FSM
:有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
状态机思维
:将一个事件分成多个完整的状态,每个状态通过输入和输出进入下一个状态。
优点
:可以把模型的多状态和多状态之间的转换条件解耦,降低程序耦合度,让程序维护变的更加容易
FSM术语:state、transition、action、transition condition
将一件事拆分为多件事,为每一件事赋予一个名字,这个名字就被称为FSM中的状态。因其状态有限,所以FSM被称为有限状态机
。
- 风扇:划分为关、一档、二挡、三挡等状态
- 电梯门:划分为关闭、正在开启、开启、正在关闭
状态转移:一个状态执行了某些动作转变为另一个状态的过程
在某个状态下,达到了某个转移条件,才会按照状态机的转移流程转移到下一状态,并执行相应的动作
当转变为一个新状态时,在这个状态下需要做的事情,称为动作
实现方式 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
分支逻辑法 | 适用于条件简单,状态固定,没有新增和扩展的需求 | 状态机代码直译,简单直接,状态逻辑比较集中,容易查看 | 对于较复杂的状态机,这种方式容易遗漏或者写错。大量的if-else和switch-case代码分支判断逻辑,可读性和可扩展性比较差,对新增和修改的场景容易引入bug |
查表法 | 通过二维数组来表达状态机,适用于复杂状态机,执行动作比较固定和简单的场景,比如游戏这种状态比较多的场景就适合用查表法 | 相对于分支逻辑的实现方式,查表法的代码实现更加清晰,可读性和可维护性更好 | 遇到比较复杂的动作,就无法通过简单的二维数组表示了,有一定的局限性 |
状态模式 | 对于状态并不多、状态转移也比较简单,但事件触发执行的动作包含的业务逻辑可能比较复杂的状态机来说,我们首选这种实现方式 | 代码结构更清晰,可以规避过多的分支逻辑判断,代码可维护性更高 | 状态模式会引入很多状态类,如果状态颗粒度控制不好,会导致状态类爆炸问题;另外逻辑比较分散,集中在状态类中,无法在一个地方整体看出整个状态机的逻辑 |
三种状态:未支付、未收货、完成
两种事件:支付、收货
状态的流转即动作:支付后状态为未收货,收货后状态为完成
支付状态枚举
// 支付状态枚举
enum PayState {
// 待支付
UNPAY = 0,
// 待收货
UNRECEIVE = 1,
// 完成
FINAL = 2,
// 错误
ERROR = 3,
};
支付事件枚举
// 支付事件枚举
enum PayEvent {
// 支付
Pay = 0,
// 收货
RECEIVE = 1,
};
#include <iostream> using namespace std; // 支付状态枚举 enum PayState { // 待支付 UNPAY = 0, // 待收货 UNRECEIVE = 1, // 完成 FINAL = 2, // 错误 ERROR = 3, }; // 支付事件枚举 enum PayEvent { // 支付 PAY = 0, // 收货 RECEIVE = 1, }; class PayStateMachine { private: PayState payState; public: PayStateMachine() { payState = PayState::UNPAY; } void executeEvent(PayEvent payEvent) { switch (payEvent) { // 支付行为发生:未支付 -> 待收货 case PAY: if (this->payState != PayState::UNPAY) { cout << "商铺不是【未支付】状态,请核验" << endl; this->payState = PayState::ERROR; break; } this->payState = PayState::UNRECEIVE; break; // 收货行为发生:待收货 -> 完成 case RECEIVE: if (this->payState != PayState::UNRECEIVE) { cout << "商铺不是【未收货】状态,请核验" << endl; this->payState = PayState::ERROR; break; } this->payState = PayState::FINAL; break; default: cout << "未设置的行为" << endl; break; } } PayState getCurrentState() { return this->payState; } }; int main() { PayStateMachine payStateMachine; cout << "当前状态为:" << payStateMachine.getCurrentState() << endl; payStateMachine.executeEvent(PayEvent::RECEIVE); cout << "当前状态为:" << payStateMachine.getCurrentState() << endl; return 0; }
运行结果:
当前状态为:0
商铺不是【未收货】状态,请核验
当前状态为:3
将状态和事件形成一个二维矩阵表,将结果态放入其中
UNPAY | UNRECEIVE | FINAL | |
---|---|---|---|
PAY | 状态转为UNRECEIVE | ERROR | ERROR |
RECEIVE | ERROR | 状态转为FINAL | ERROR |
将结果态转为一个二维数组进行存储,用的时候使用状态和事件枚举的value值作为索引,获取结果态
#include <iostream> #include <vector> using namespace std; // 支付状态枚举 enum PayState { // 待支付 UNPAY = 0, // 待收货 UNRECEIVE = 1, // 完成 FINAL = 2, // 错误 ERROR = 3, }; // 支付事件枚举 enum PayEvent { // 支付 PAY = 0, // 收货 RECEIVE = 1, }; class PayStateMachine { public: // 初始化 PayStateMachine() { currentPayState = PayState::UNPAY; } // 使用状态和事件枚举的value值作为索引,获取结果态 void executeEvent(PayEvent payEvent) { this->currentPayState = payStateTable[this->currentPayState][payEvent]; } // 获取当前状态 PayState getCurrentState() { return this->currentPayState; } private: // 当前状态 PayState currentPayState; // 将结果态转为一个二维数组进行存储 vector<vector<PayState>> payStateTable = { {UNRECEIVE, ERROR, ERROR}, {ERROR, FINAL, ERROR} }; }; int main() { PayStateMachine payStateMachine; cout << "当前状态为:" << payStateMachine.getCurrentState() << endl; payStateMachine.executeEvent(PayEvent::PAY); cout << "当前状态为:" << payStateMachine.getCurrentState() << endl; payStateMachine.executeEvent(PayEvent::RECEIVE); cout << "当前状态为:" << payStateMachine.getCurrentState() << endl; return 0; }
运行结果:
当前状态为:0
当前状态为:1
当前状态为:2
状态模式,定义状态接口,并将行为规定为抽象方法,实现对应三种状态以及行为方法(实现状态流转逻辑)。
定义状态机,并依赖状态接口。
同时,每个具体的状态又依赖状态机。
即状态机和各个状态类之间是双向依赖关系,因为每个状态需要依靠状态机修改状态
状态模式将每个状态的实现都封装在一个类中,每个状态类的实现相对独立,使得添加新状态或修改现有状态变得更加容易,避免了使用大量的条件语句来控制对象的行为。但是如果状态过多,会导致类的数量增加,可能会使得代码结构复杂。
状态模式基本结构
State
:定义一个接口,用于封装与Context的一个特定状态相关的行为ConcreteState
(具体状态): 负责处理Context在状态改变时的行为, 每一个具体状态子类实现一个与Context的一个状态相关的行为。Context
(上下文): 维护一个具体状态子类的实例,这个实例定义当前的状态
#include <iostream> #include <vector> #include <string> // 状态接口 class State { public: virtual std::string handle() = 0; // 处理状态的方法 }; // 具体状态类 class OnState : public State { public: std::string handle() override { return "Light is ON"; } }; class OffState : public State { public: std::string handle() override { return "Light is OFF"; } }; class BlinkState : public State { public: std::string handle() override { return "Light is Blinking"; } }; // 上下文类 class Light { private: State* state; // 当前状态 public: Light() : state(new OffState()) {} // 初始状态为关闭 void setState(State* newState) { // 设置新的状态 delete state; // 释放之前的状态对象 state = newState; } std::string performOperation() { // 执行当前状态的操作 return state->handle(); } ~Light() { delete state; // 释放内存 } }; int main() { // 读取要输入的命令数量 int n; std::cin >> n; std::cin.ignore(); // 消耗掉整数后的换行符 // 创建一个Light对象 Light light; // 处理用户输入的每个命令 for (int i = 0; i < n; i++) { // 读取命令并去掉首尾空白字符 std::string command; std::getline(std::cin, command); // 根据命令执行相应的操作 if (command == "ON") { light.setState(new OnState()); } else if (command == "OFF") { light.setState(new OffState()); } else if (command == "BLINK") { light.setState(new BlinkState()); } else { // 处理无效命令 std::cout << "Invalid command: " << command << std::endl; } // 在每个命令后显示灯的当前状态 std::cout << light.performOperation() << std::endl; } return 0; }
state_machine.h
#ifndef STATE_MACHINE_H #define STATE_MACHINE_H #include <memory> #include <iostream> namespace state_machine { // 定义一个枚举类StateList,表示车辆的不同状态 enum class StateList : int32_t { MOVE_FORWARD, // 车辆向前移动 TRAFFIC_LIGHT_STOP, // 遇到红灯停车 LANE_CHANGE, // 车辆变更车道 STOP_SIGN_STOP, // 遇到停车标志停车 OBSTACLE_AVOIDANCE, // 避障 MISSION_COMPLETE = 100, // 任务完成 EMERGENCY = -1, // 紧急情况 }; // 定义一个枚举类TrafficLight,表示交通信号灯的状态 enum class TrafficLight : int32_t { RED, // 红灯 GREEN, // 绿灯 UNKNOWN, // 未知 }; // 定义一个枚举类ChangeFlag,表示车辆变更车道的方向 enum class ChangeFlag : int32_t { straight, // 直行 right, // 向右变更车道 left, // 向左变更车道 unknown = -1, // 未知方向 }; // 用于将枚举类类型转换为整数类型 // 可以将枚举类的实例转换为整数类型,便于进行数值计算或其他整数相关的操作 template <class T> typename std::underlying_type<T>::type enumToInteger(T t) { return static_cast<typename std::underlying_type<T>::type>(t); } // Forward Decralation class StateContext; // abstract class for states class BaseState { public: virtual ~BaseState() = default; // 确保子类可以正确地删除基类对象 virtual void update(StateContext *context) = 0; // 用于更新状态 virtual int32_t getStateName() // 返回当前状态的名称 { return 0; }; virtual std::unique_ptr<std::string> getStateNameString() // 返回当前状态的名称字符串 { return 0; }; }; // State : MOVE_FORWARD class StateMoveForward : public BaseState { public: // 更新状态逻辑 void update(StateContext *context) override; // 获取状态名称(整数表示) int32_t getStateName() override { return enumToInteger(StateList::MOVE_FORWARD); } // 获取状态名称(字符串表示) std::unique_ptr<std::string> getStateNameString() override { return std::unique_ptr<std::string>(new std::string("MOVE_FORWARD")); } // 静态方法,用于创建 StateMoveForward 对象 static std::unique_ptr<BaseState> create() { return std::unique_ptr<BaseState>(new StateMoveForward); }; private: StateMoveForward() = default; }; // State : TRAFFIC_LIGHT_STOP class StateTrafficLightStop : public BaseState { public: // 更新状态逻辑 void update(StateContext *context) override; // 获取状态名称(整数表示) int32_t getStateName() override { return enumToInteger(StateList::TRAFFIC_LIGHT_STOP); } // 获取状态名称(字符串表示) std::unique_ptr<std::string> getStateNameString() override { return std::unique_ptr<std::string>(new std::string("TRAFFIC_LIGHT_STOP")); } // 静态方法,用于创建 StateTrafficLightStop 对象 static std::unique_ptr<BaseState> create() { return std::unique_ptr<BaseState>(new StateTrafficLightStop); }; private: StateTrafficLightStop() = default; }; // State : LANE_CHANGE class StateLaneChange : public BaseState { public: // 更新状态逻辑 void update(StateContext *context) override; // 获取状态名称(整数表示) int32_t getStateName() override { return enumToInteger(StateList::LANE_CHANGE); } // 获取状态名称(字符串表示) std::unique_ptr<std::string> getStateNameString() override { return std::unique_ptr<std::string>(new std::string("LANE_CHANGE")); } // 静态方法,用于创建 StateLaneChange 对象 static std::unique_ptr<BaseState> create() { return std::unique_ptr<BaseState>(new StateLaneChange); }; private: StateLaneChange() = default; }; // State : STOP_SIGN_STOP class StateStopSignStop : public BaseState { public: // 更新状态逻辑 void update(StateContext *context) override; // 获取状态名称(整数表示) int32_t getStateName() override { return enumToInteger(StateList::STOP_SIGN_STOP); } // 获取状态名称(字符串表示) std::unique_ptr<std::string> getStateNameString() override { return std::unique_ptr<std::string>(new std::string("STOP_SIGN_STOP")); } // 静态方法,用于创建StateStopSignStop对象 static std::unique_ptr<BaseState> create() { return std::unique_ptr<BaseState>(new StateStopSignStop); }; private: StateStopSignStop() = default; }; // State : Obstacle Avoidance class StateObstacleAvoidance : public BaseState { public: void update(StateContext *context) override; int32_t getStateName() override { return enumToInteger(StateList::STOP_SIGN_STOP); } std::unique_ptr<std::string> getStateNameString() override { return std::unique_ptr<std::string>(new std::string("OBSTACLE_AVOIDANCE")); } static std::unique_ptr<BaseState> create() { return std::unique_ptr<BaseState>(new StateObstacleAvoidance); }; private: StateObstacleAvoidance() = default; }; // State : EMERGENCY class StateEmergency : public BaseState { public: void update(StateContext *context) override; int32_t getStateName() override { return enumToInteger(StateList::EMERGENCY); } std::unique_ptr<std::string> getStateNameString() override { return std::unique_ptr<std::string>(new std::string("EMERGENCY")); } static std::unique_ptr<BaseState> create() { return std::unique_ptr<BaseState>(new StateEmergency); }; private: StateEmergency() = default; }; // State : MISSION_COMPLETE class StateMissionComplete : public BaseState { public: void update(StateContext *context) override; int32_t getStateName() override { return enumToInteger(StateList::MISSION_COMPLETE); } std::unique_ptr<std::string> getStateNameString() override { return std::unique_ptr<std::string>(new std::string("MISSION_COMPLETE")); } static std::unique_ptr<BaseState> create() { return std::unique_ptr<BaseState>(new StateMissionComplete); }; private: StateMissionComplete() = default; }; // 包含状态机当前状态的上下文对象,它包含了当前状态、交通灯颜色和车辆变更车道等信息 class StateContext { public: StateContext() : state_(StateMoveForward::create()), light_color_(TrafficLight::UNKNOWN), change_flag_(ChangeFlag::unknown){}; // 设置状态机当前状态 void setState(std::unique_ptr<BaseState> newState) { state_ = std::move(newState); }; // 更新状态机状态 void update() { state_->update(this); } // 设置交通灯颜色 void setLightColor(const int32_t &msg) { light_color_ = static_cast<TrafficLight>(msg); } // 设置变道方向 void setChangeFlag(const int32_t &msg) { change_flag_ = static_cast<ChangeFlag>(msg); } // 获取当前交通灯颜色 TrafficLight getLightColor() const { return light_color_; } // 获取当前变道方向 ChangeFlag getChangeFlag() const { return change_flag_; } // 获取当前状态机的整数表示状态名称 int32_t getCurrentState() const { return state_->getStateName(); } // 获取当前状态机的字符串表示状态名称 std::unique_ptr<std::string> getCurrentStateString() const { return state_->getStateNameString(); } private: std::unique_ptr<BaseState> state_; TrafficLight light_color_; ChangeFlag change_flag_; }; } // state_machine #endif // STATE_MACHINE_H
state_machine.cpp
#include "state_machine.h" namespace state_machine { void StateTrafficLightStop::update(StateContext *context) { // 如果交通灯颜色为绿色,表示可以继续行驶,将状态机转移到StateMoveForward状态 if (context->getLightColor() == TrafficLight::GREEN) context->setState(StateMoveForward::create()); } void StateMoveForward::update(StateContext *context) { // 如果交通灯颜色为红色,表示需要停车,将状态机转移到 StateTrafficLightStop 状态 if (context->getLightColor() == TrafficLight::RED) context->setState(StateTrafficLightStop::create()); // 如果变化标志为右转或左转,将状态机转移到 StateLaneChange 状态 if(context->getChangeFlag() == ChangeFlag::right || context->getChangeFlag() == ChangeFlag::left) context->setState(StateLaneChange::create()); } void StateLaneChange::update(StateContext *context) { // 如果变化标志为直行,将状态机转移到 StateMoveForward 状态 if(context->getChangeFlag() == ChangeFlag::straight) context->setState(StateMoveForward::create()); } void StateStopSignStop::update(StateContext *context) { // stop sign stop } void StateMissionComplete::update(StateContext *context) { // Mission complete } void StateEmergency::update(StateContext *context) { // Emergency } void StateObstacleAvoidance::update(StateContext *context) { // Obstacle Avoidance } } // state_machine
有限状态机原理及三种模式代码实现如上,错误之处望读者指正。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。