状态机浅析

状态机是处理状态依赖型行为的高效工具,通过结构化建模状态转换,解决了传统条件判断的冗余和混乱问题。它在设备控制、流程管理、协议解析等场景中表现优异,核心优势在于逻辑清晰、可扩展性强和易于调试。

一、介绍

1. 概念

状态机(State Machine)是一种用于描述对象或系统在不同状态之间转换规律的数学模型,它由状态事件转换动作四部分组成:

  • 状态:系统在某一时刻的稳定状况(如交通灯的“红灯”“绿灯”)。
  • 事件:触发状态转换的外部或内部信号(如“超时”“按钮按下”)。
  • 转换:在特定事件发生时,从一个状态切换到另一个状态的规则(如“红灯超时后切换到绿灯”)。
  • 动作:状态转换时执行的操作(如“切换绿灯时点亮绿灯LED”)。
2. 优点
  1. 逻辑清晰
    状态和转换规则被显式定义,代码结构模块化,便于理解和维护。例如,交通灯的状态机可直观列出“红灯→超时→黄灯”等转换,无需嵌套if-else
  2. 可扩展性强
    新增状态或转换规则时,只需添加新的状态定义和转换逻辑,无需修改现有代码(符合开闭原则)。
  3. 易调试与测试
    状态机的行为可通过状态图可视化,便于梳理所有可能的状态转换路径,确保覆盖边界场景(如异常事件下的状态回滚)。
  4. 降低复杂度
    将复杂的条件判断转化为状态间的映射关系,减少代码嵌套层级,尤其适合多状态、多分支的场景(如协议解析中的状态切换)。
  5. 标准化与复用
    状态机模型是通用的设计模式,可通过模板(如C++的StateMachine类)封装核心逻辑,在不同场景中复用。
3. 适应场景

状态机适用于行为与状态强相关状态转换规则明确的场景,典型包括:

  1. 设备控制
    • 交通灯(红→黄→绿→红的循环);
    • 电梯(待机→上行→开门→下行的状态切换)。
  2. 流程管理
    • 订单系统(待支付→已支付→发货→完成);
    • 工作流审批(提交→部门审核→总经理审核→通过)。
  3. 协议解析
    • 网络协议(TCP连接的建立→数据传输→断开);
    • 串口通信(起始位→数据位→校验位→停止位)。
  4. 游戏逻辑
    • 角色状态( idle→行走→攻击→受伤→死亡)。

二、状态机类别

常见的状态机实现方式根据抽象程度、灵活性和适用场景的不同,可分为以下几类,各有其特点和适用范围。以下均以交通信号灯状态机为例,提供一个示例实现。

模拟真实交通信号灯的工作场景,可以通过输入命令与状态机交互:
- 输入`e`触发紧急情况
- 输入`p`切换电源状态
- 输入`q`退出程序
1. 硬编码状态机(Hard-coded State Machines)

核心思想:用 if-elseswitch-case 直接硬编码状态转换逻辑,是最直观的实现方式。

#include <iostream>
#include <chrono>
#include <thread>
using namespace std;// 状态和事件定义
enum State { RED, GREEN, YELLOW };
enum Event { TIME_OUT, EMERGENCY };State currentState = RED; // 初始状态:红灯// 处理事件
void processEvent(Event event) {switch (currentState) {case RED:if (event == TIME_OUT) {cout << "\n红灯→绿灯\n";currentState = GREEN;} else if (event == EMERGENCY) {cout << "\n红灯→黄灯(紧急)\n";currentState = YELLOW;}break;case GREEN:if (event == TIME_OUT) {cout << "\n绿灯→黄灯\n";currentState = YELLOW;} else if (event == EMERGENCY) {cout << "\n绿灯→黄灯(紧急)\n";currentState = YELLOW;}break;case YELLOW:if (event == TIME_OUT) {cout << "\n黄灯→红灯\n";currentState = RED;} else if (event == EMERGENCY) {cout << "\n黄灯保持(紧急)\n"; // 紧急时黄灯闪烁}break;}
}// 运行红绿灯
void run() {while (true) {int duration = 0;switch (currentState) {case RED: duration = 5; break;   // 红灯5秒case GREEN: duration = 4; break; // 绿灯4秒case YELLOW: duration = 2; break;// 黄灯2秒}// 显示当前状态并等待cout << (currentState == RED ? "红灯" : currentState == GREEN ? "绿灯" : "黄灯") << "亮(" << duration << "秒)";for (int i = 0; i < duration; ++i) {cout << "."; cout.flush();this_thread::sleep_for(chrono::seconds(1));}// 定时结束,触发事件processEvent(TIME_OUT);}
}int main() {thread t(run);t.detach();// 模拟紧急事件输入string input;while (cin >> input) {if (input == "e") processEvent(EMERGENCY);}return 0;
}
特点:
  • 优点:实现简单,无需额外框架,适合状态少、转换规则简单的场景(如简易设备控制)。
  • 缺点:状态或事件增多时,代码臃肿(嵌套层级深)、维护困难(修改一处可能影响多处)。
  • 适用场景:嵌入式小设备、简单流程(如LED闪烁控制)。
2. 状态表驱动的状态机(State Table-driven Machines)
实现

核心思想:用表格(数组/字典) 存储“状态-事件-动作-下一状态”的映射关系,通过遍历表格处理状态转换(本文之前示例均为此方式)。

#include <iostream>
#include <string>
#include <chrono>
#include <thread>// 1. 定义事件类型
enum TrafficEvent {TIME_OUT,       // 定时结束事件EMERGENCY,      // 紧急情况事件POWER_OFF,      // 断电事件POWER_ON,       // 上电事件NONE            // 无事件(终止符)
};// 2. 前向声明状态数组
extern const class TrafficState RedLight[];
extern const class TrafficState GreenLight[];
extern const class TrafficState YellowLight[];
extern const class TrafficState OffState[];// 3. 状态机类(交通信号灯控制器)
class TrafficLightController {
public:// 状态处理函数的参数类型struct Param {int duration;       // 持续时间(秒)std::string reason; // 事件原因描述};// 构造函数:初始化状态为关闭TrafficLightController() : currentState(OffState) {}// 获取当前状态名称std::string getCurrentStateName() const;// 处理事件并转换状态void handleEvent(TrafficEvent event, const Param& param);// 运行状态机(自动计时切换)void run();// 紧急情况处理void triggerEmergency() {Param param{0, "手动触发紧急模式"};handleEvent(EMERGENCY, param);}// 电源控制void powerToggle() {Param param{0, ""};if (currentState == OffState) {param.reason = "电源开启";handleEvent(POWER_ON, param);} else {param.reason = "电源关闭";handleEvent(POWER_OFF, param);}}// 静态处理函数(用于状态表,避免lambda转换问题)static void redToGreenHandler(const Param& param) {handleGreenLightOn(param);}static void redEmergencyHandler(const Param& param) {handleEmergency(param);}static void redPowerOffHandler(const Param& param) {handleLightOff(param);}static void greenToYellowHandler(const Param& param) {handleYellowLightOn(param);}static void greenEmergencyHandler(const Param& param) {handleEmergency(param);}static void greenPowerOffHandler(const Param& param) {handleLightOff(param);}static void yellowToRedHandler(const Param& param) {handleRedLightOn(param);}static void yellowEmergencyHandler(const Param& param) {handleEmergency(param);}static void yellowPowerOffHandler(const Param& param) {handleLightOff(param);}static void offToRedHandler(const Param& param) {handleRedLightOn(param);}private:const TrafficState* currentState; // 当前状态// 状态处理函数实现(交通信号灯的具体行为)static void handleRedLightOn(const Param& param) {std::cout << "\n[红灯亮] 禁止通行,持续 " << param.duration << " 秒 " << (param.reason.empty() ? "" : "(" + param.reason + ")") << std::endl;}static void handleGreenLightOn(const Param& param) {std::cout << "\n[绿灯亮] 可以通行,持续 " << param.duration << " 秒 "<< (param.reason.empty() ? "" : "(" + param.reason + ")") << std::endl;}static void handleYellowLightOn(const Param& param) {std::cout << "\n[黄灯亮] 准备停止,持续 " << param.duration << " 秒 "<< (param.reason.empty() ? "" : "(" + param.reason + ")") << std::endl;}static void handleLightOff(const Param& param) {std::cout << "\n[灯关闭] 所有灯光关闭 "<< (param.reason.empty() ? "" : "(" + param.reason + ")") << std::endl;}static void handleEmergency(const Param& param) {std::cout << "\n[紧急模式] 所有灯光闪烁 "<< (param.reason.empty() ? "" : "(" + param.reason + ")") << std::endl;}
};// 4. 状态结构体定义(状态表的核心)
class TrafficState {
public:TrafficEvent event;                  // 触发事件const TrafficState* nextState;       // 事件发生后转移到的状态void (*handler)(const TrafficLightController::Param&); // 改为静态函数指针const char* stateName;               // 状态名称(用于打印)
};// 5. 状态转移表定义(核心逻辑)
// 红灯状态的转移规则
const TrafficState RedLight[] = {{TIME_OUT,    GreenLight,  &TrafficLightController::redToGreenHandler,   "红灯"},{EMERGENCY,   YellowLight, &TrafficLightController::redEmergencyHandler, "红灯"},{POWER_OFF,   OffState,    &TrafficLightController::redPowerOffHandler,  "红灯"},{NONE,        nullptr,     nullptr,                                      nullptr}
};// 绿灯状态的转移规则
const TrafficState GreenLight[] = {{TIME_OUT,    YellowLight, &TrafficLightController::greenToYellowHandler,  "绿灯"},{EMERGENCY,   YellowLight, &TrafficLightController::greenEmergencyHandler, "绿灯"},{POWER_OFF,   OffState,    &TrafficLightController::greenPowerOffHandler,  "绿灯"},{NONE,        nullptr,     nullptr,                                       nullptr}
};// 黄灯状态的转移规则
const TrafficState YellowLight[] = {{TIME_OUT,    RedLight,    &TrafficLightController::yellowToRedHandler,    "黄灯"},{EMERGENCY,   YellowLight, &TrafficLightController::yellowEmergencyHandler, "黄灯"},{POWER_OFF,   OffState,    &TrafficLightController::yellowPowerOffHandler,  "黄灯"},{NONE,        nullptr,     nullptr,                                        nullptr}
};// 关闭状态的转移规则
const TrafficState OffState[] = {{POWER_ON,    RedLight,    &TrafficLightController::offToRedHandler,    "关闭"},{NONE,        nullptr,     nullptr,                                    nullptr}
};// 6. 状态机类成员函数实现
std::string TrafficLightController::getCurrentStateName() const {return currentState->stateName;
}void TrafficLightController::handleEvent(TrafficEvent event, const Param& param) {// 遍历当前状态的转移表,查找匹配的事件for (int i = 0; ; i++) {const TrafficState& entry = currentState[i];if (entry.event == NONE) {// 未找到匹配的事件处理规则std::cout << "[警告] 状态 " << currentState->stateName << " 不处理事件类型 " << event << std::endl;return;}if (entry.event == event) {// 调用事件处理函数entry.handler(param);// 状态转移const TrafficState* prevState = currentState;currentState = entry.nextState;std::cout << "[状态切换] 从 " << prevState->stateName << " 切换到 " << currentState->stateName << std::endl;return;}}
}void TrafficLightController::run() {std::cout << "交通信号灯系统启动..." << std::endl;while (true) {// 根据当前状态设置不同的定时时间int duration = 0;if (currentState == RedLight) {duration = 10; // 红灯持续10秒} else if (currentState == GreenLight) {duration = 8;  // 绿灯持续8秒} else if (currentState == YellowLight) {duration = 3;  // 黄灯持续3秒} else if (currentState == OffState) {// 如果是关闭状态,等待1秒后再次检查std::this_thread::sleep_for(std::chrono::seconds(1));continue;}// 等待定时结束for (int i = 0; i < duration; i++) {std::cout << ".";std::cout.flush();std::this_thread::sleep_for(std::chrono::seconds(1));}// 定时结束,触发状态切换事件Param param{duration, "定时结束"};handleEvent(TIME_OUT, param);}
}// 7. 演示程序
int main() {TrafficLightController controller;// 上电(从关闭状态切换到红灯)controller.powerToggle();// 启动状态机自动运行std::thread runner(&TrafficLightController::run, &controller);runner.detach();// 模拟用户输入控制std::string input;while (true) {std::cout << "\n输入命令 (e:紧急情况, p:电源开关, q:退出): ";std::cin >> input;if (input == "e") {controller.triggerEmergency();} else if (input == "p") {controller.powerToggle();} else if (input == "q") {std::cout << "程序退出" << std::endl;break;} else {std::cout << "未知命令,请重新输入" << std::endl;}}return 0;
}
1. 核心组成部分
  • 状态定义:红灯(RedLight)、绿灯(GreenLight)、黄灯(YellowLight)、关闭(OffState)四种状态
  • 事件类型:定时结束(TIME_OUT)、紧急情况(EMERGENCY)、电源开关(POWER_ON/POWER_OFF)
  • 状态转移表:每个状态都定义了对不同事件的响应规则和目标状态
  • 处理函数:每种状态切换都有对应的行为(如灯光提示、持续时间显示)
2. 状态机工作流程
  1. 系统启动后处于关闭状态,上电后切换到红灯
  2. 红灯持续10秒后自动切换到绿灯(TIME_OUT事件)
  3. 绿灯持续8秒后自动切换到黄灯(TIME_OUT事件)
  4. 黄灯持续3秒后自动切换到红灯(TIME_OUT事件)
  5. 遇到紧急情况时,所有状态都切换到黄灯闪烁模式
  6. 支持电源开关控制,可随时关闭或开启信号灯
3. 状态表驱动的优势
  • 逻辑清晰:状态转换规则集中定义在状态表中,一目了然
  • 易于扩展:新增状态或事件只需修改状态表,无需改动核心逻辑
  • 可维护性高:状态和行为分离,修改状态转换或行为都很方便
  • 可测试性好:可以通过发送特定事件来测试状态机的响应
优化
优化点
  1. 模板化状态机框架

    • 定义 StateMachine<T, P> 模板类:通过 current 指针指向当前状态,遍历状态表(p->nextState != nullptr 作为终止条件),匹配事件后执行动作并切换状态。
    • 模板参数 T 为状态机所属的目标类(如 TrafficLightController),P 为事件参数类型,实现通用化复用。
  2. 状态管理逻辑

    • 状态结构体 State<T, P> 包含 inputEvent(事件)、action(处理函数)、nextState(下一个状态)、errorState(错误状态)。
    • 通过 currentState() 接口获取当前状态。
  3. 事件处理流程

    • ProcessEvent 函数逻辑:遍历当前状态表(for (State* p = current; p->nextState != NULL; p++)),匹配事件后执行 action,再切换到 nextState
    • 支持错误状态处理(errorState),可在动作执行失败时切换(示例中简化处理,实际可扩展为返回执行结果判断)。
  4. 低耦合与可扩展性

    • 具体业务逻辑(如交通信号灯的状态名称、定时时间、动作实现)封装在 TrafficLightController 中,与通用状态机框架解耦。
    • 新增状态或事件时,只需扩展状态转移表(如添加 FlashingState 闪烁状态),无需修改 StateMachine 核心逻辑。
#include <iostream>
#include <string>
#include <chrono>
#include <thread>// 1. 提前声明参数结构体和控制器类
struct TrafficParam;
class TrafficLightController;// 2. 通用状态结构体(模板化)
template <class T, class P>
struct State {int inputEvent;               // 输入事件void (T::*action)(int, const P&); // 事件处理动作State<T, P>* nextState;       // 正常下一个状态State<T, P>* errorState;      // 错误状态
};// 3. 通用状态机模板类
template <class T, class P>
class StateMachine {
public:// 构造函数:绑定目标对象和初始状态StateMachine(T* target, State<T, P>* initialState) : target(target), current(initialState) {}// 事件处理核心函数void ProcessEvent(int event, const P& param) {for (State<T, P>* p = current; p->nextState != nullptr; p++) {if (p->inputEvent == event) {if (p->action != nullptr) {(target->*(p->action))(event, param);}current = p->nextState;return;}}std::cout << "[警告] 未处理事件: " << event << std::endl;}// 获取当前状态State<T, P>* currentState() const {return current;}protected:T* target;               // 目标对象State<T, P>* current;    // 当前状态
};// 4. 定义参数结构体(在控制器类外部,解决不完全类型问题)
struct TrafficParam {int duration;       // 持续时间(秒)std::string reason; // 事件描述
};// 5. 交通信号灯控制器(继承通用状态机)
class TrafficLightController : public StateMachine<TrafficLightController, TrafficParam> {
public:// 事件类型(用整数表示)enum Event {TIME_OUT = 1,EMERGENCY = 2,POWER_OFF = 3,POWER_ON = 4,NONE = 0};// 构造函数:初始化状态机TrafficLightController() : StateMachine<TrafficLightController, TrafficParam>(this, &OffState[0]) {}// 启动状态机void run() {std::cout << "交通信号灯系统启动...\n" << std::endl;while (true) {int duration = 0;// 访问基类的currentState()方法if (StateMachine::currentState() == &RedState[0]) duration = 5;else if (StateMachine::currentState() == &GreenState[0]) duration = 4;else if (StateMachine::currentState() == &YellowState[0]) duration = 2;else if (StateMachine::currentState() == &OffState[0]) {std::this_thread::sleep_for(std::chrono::seconds(1));continue;}// 等待定时结束std::cout << getStateName(StateMachine::currentState()) << "亮(" << duration << "秒)";for (int i = 0; i < duration; ++i) {std::cout << ".";std::cout.flush();std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << std::endl;// 触发定时结束事件TrafficParam param{duration, "定时结束"};StateMachine::ProcessEvent(TIME_OUT, param);}}// 触发紧急情况void triggerEmergency() {TrafficParam param{0, "手动紧急触发"};StateMachine::ProcessEvent(EMERGENCY, param);}// 切换电源void powerToggle() {TrafficParam param{0, ""};if (StateMachine::currentState() == &OffState[0]) {param.reason = "电源开启";StateMachine::ProcessEvent(POWER_ON, param);} else {param.reason = "电源关闭";StateMachine::ProcessEvent(POWER_OFF, param);}}// 状态名称映射std::string getStateName(State<TrafficLightController, TrafficParam>* state) {if (state == &RedState[0]) return "红灯";if (state == &GreenState[0]) return "绿灯";if (state == &YellowState[0]) return "黄灯";if (state == &OffState[0]) return "关闭";return "未知状态";}// 事件处理动作(成员函数)void onRedToGreen(int event, const TrafficParam& param) {std::cout << "[动作] 红灯→绿灯," << param.reason << std::endl;}void onGreenToYellow(int event, const TrafficParam& param) {std::cout << "[动作] 绿灯→黄灯," << param.reason << std::endl;}void onYellowToRed(int event, const TrafficParam& param) {std::cout << "[动作] 黄灯→红灯," << param.reason << std::endl;}void onEmergency(int event, const TrafficParam& param) {std::cout << "[动作] 触发紧急模式," << param.reason << std::endl;}void onPowerOff(int event, const TrafficParam& param) {std::cout << "[动作] 电源关闭," << param.reason << std::endl;}void onPowerOn(int event, const TrafficParam& param) {std::cout << "[动作] 电源开启," << param.reason << std::endl;}// 状态转移表(静态成员)static State<TrafficLightController, TrafficParam> RedState[];static State<TrafficLightController, TrafficParam> GreenState[];static State<TrafficLightController, TrafficParam> YellowState[];static State<TrafficLightController, TrafficParam> OffState[];
};// 6. 初始化状态转移表
State<TrafficLightController, TrafficParam> TrafficLightController::RedState[] = {{TIME_OUT,   &TrafficLightController::onRedToGreen, GreenState, nullptr},{EMERGENCY,  &TrafficLightController::onEmergency,  YellowState, nullptr},{POWER_OFF,  &TrafficLightController::onPowerOff,   OffState, nullptr},{NONE,       nullptr,                               nullptr, nullptr}
};State<TrafficLightController, TrafficParam> TrafficLightController::GreenState[] = {{TIME_OUT,   &TrafficLightController::onGreenToYellow, YellowState, nullptr},{EMERGENCY,  &TrafficLightController::onEmergency,     YellowState, nullptr},{POWER_OFF,  &TrafficLightController::onPowerOff,      OffState, nullptr},{NONE,       nullptr,                                  nullptr, nullptr}
};State<TrafficLightController, TrafficParam> TrafficLightController::YellowState[] = {{TIME_OUT,   &TrafficLightController::onYellowToRed, RedState, nullptr},{EMERGENCY,  &TrafficLightController::onEmergency,   YellowState, nullptr},{POWER_OFF,  &TrafficLightController::onPowerOff,    OffState, nullptr},{NONE,       nullptr,                                nullptr, nullptr}
};State<TrafficLightController, TrafficParam> TrafficLightController::OffState[] = {{POWER_ON,   &TrafficLightController::onPowerOn, RedState, nullptr},{NONE,       nullptr,                            nullptr, nullptr}
};// 7. 主函数
int main() {TrafficLightController controller;controller.powerToggle(); // 上电// 启动自动运行线程std::thread runner(&TrafficLightController::run, &controller);runner.detach();// 用户交互std::string input;while (true) {std::cout << "\n输入命令 (e:紧急情况, p:电源开关, q:退出): ";std::cin >> input;if (input == "e") {controller.triggerEmergency();} else if (input == "p") {controller.powerToggle();} else if (input == "q") {std::cout << "程序退出" << std::endl;return 0;} else {std::cout << "未知命令,请重新输入" << std::endl;}}
}
编译与运行
g++ -std=c++11 main.cpp -o main -lpthread
./main
3. 面向对象状态机(Object-oriented State Machines)

核心思想:将每个状态封装为独立的类,通过多态实现状态转换,符合面向对象的“单一职责原则”。:

#include <iostream>
#include <chrono>
#include <thread>
using namespace std;// 前向声明
class TrafficLight;// 状态基类
class State {
public:virtual string getName() = 0;          // 获取状态名称virtual int getDuration() = 0;         // 获取持续时间virtual void onTimeout(TrafficLight* tl) = 0; // 处理超时事件virtual void onEmergency(TrafficLight* tl) = 0; // 处理紧急事件virtual ~State() = default;
};// 红绿灯控制器
class TrafficLight {
public:// 状态实例(单例)class RedState : public State {public:string getName() override { return "红灯"; }int getDuration() override { return 5; }void onTimeout(TrafficLight* tl) override;void onEmergency(TrafficLight* tl) override;};class GreenState : public State {public:string getName() override { return "绿灯"; }int getDuration() override { return 4; }void onTimeout(TrafficLight* tl) override;void onEmergency(TrafficLight* tl) override;};class YellowState : public State {public:string getName() override { return "黄灯"; }int getDuration() override { return 2; }void onTimeout(TrafficLight* tl) override;void onEmergency(TrafficLight* tl) override;};// 初始化状态为红灯TrafficLight() : currentState(&redState) {}// 处理事件void triggerTimeout() { currentState->onTimeout(this); }void triggerEmergency() { currentState->onEmergency(this); }// 切换状态void setState(State* state) { currentState = state; }// 获取状态实例(供状态类调用)RedState* getRedState() { return &redState; }GreenState* getGreenState() { return &greenState; }YellowState* getYellowState() { return &yellowState; }// 运行void run() {while (true) {string name = currentState->getName();int duration = currentState->getDuration();cout << name << "亮(" << duration << "秒)";for (int i = 0; i < duration; ++i) {cout << "."; cout.flush();this_thread::sleep_for(chrono::seconds(1));}triggerTimeout(); // 超时事件}}private:RedState redState;GreenState greenState;YellowState yellowState;State* currentState;
};// 实现状态转换逻辑
void TrafficLight::RedState::onTimeout(TrafficLight* tl) {cout << "\n[转换] 红灯→绿灯\n";tl->setState(tl->getGreenState());
}
void TrafficLight::RedState::onEmergency(TrafficLight* tl) {cout << "\n[转换] 红灯→黄灯(紧急)\n";tl->setState(tl->getYellowState());
}void TrafficLight::GreenState::onTimeout(TrafficLight* tl) {cout << "\n[转换] 绿灯→黄灯\n";tl->setState(tl->getYellowState());
}
void TrafficLight::GreenState::onEmergency(TrafficLight* tl) {cout << "\n[转换] 绿灯→黄灯(紧急)\n";tl->setState(tl->getYellowState());
}void TrafficLight::YellowState::onTimeout(TrafficLight* tl) {cout << "\n[转换] 黄灯→红灯\n";tl->setState(tl->getRedState());
}
void TrafficLight::YellowState::onEmergency(TrafficLight* tl) {cout << "\n[转换] 黄灯保持(紧急)\n";
}int main() {TrafficLight light;thread t(&TrafficLight::run, &light);t.detach();// 模拟紧急事件string input;while (cin >> input) {if (input == "e") light.triggerEmergency();}return 0;
}

特点

  • 优点:状态逻辑完全封装在类中,修改一个状态不影响其他状态,可扩展性极强(新增状态只需新增类)。
  • 缺点:类数量多(每个状态一个类),实现较繁琐,适合复杂场景。
  • 适用场景:复杂状态机(如游戏角色状态、工业设备控制逻辑)。
4. 框架/库实现的状态机(Framework-based State Machines)

核心思想:使用成熟的状态机库(如 Boost.Statechart、Qt State Machine Framework),通过配置或 DSL(领域特定语言)定义状态机,无需重复开发基础逻辑。

// Boost.Statechart 伪代码:
#include <iostream>
#include <chrono>
#include <thread>
#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/transition.hpp>namespace sc = boost::statechart;// 事件定义
struct EvTimeout : sc::event<EvTimeout> {};       // 定时结束
struct EvEmergency : sc::event<EvEmergency> {};   // 紧急情况// 状态机:红绿灯系统
struct TrafficLight : sc::state_machine<TrafficLight, struct RedState> {};// 红灯状态
struct RedState : sc::simple_state<RedState, TrafficLight> {RedState() { cout << "\n进入红灯状态(5秒)\n"; }// 转换规则:超时→绿灯,紧急→黄灯typedef sc::transition<EvTimeout, struct GreenState> +sc::transition<EvEmergency, struct YellowState> reactions;
};// 绿灯状态
struct GreenState : sc::simple_state<GreenState, TrafficLight> {GreenState() { cout << "\n进入绿灯状态(4秒)\n"; }// 转换规则:超时→黄灯,紧急→黄灯typedef sc::transition<EvTimeout, struct YellowState> +sc::transition<EvEmergency, struct YellowState> reactions;
};// 黄灯状态
struct YellowState : sc::simple_state<YellowState, TrafficLight> {YellowState() { cout << "\n进入黄灯状态(2秒)\n"; }// 转换规则:超时→红灯,紧急→自身(保持)typedef sc::transition<EvTimeout, RedState> +sc::transition<EvEmergency, YellowState> reactions;
};// 运行状态机
void run(TrafficLight& light) {while (true) {// 根据当前状态设置定时int duration = 0;if (light.state_cast<RedState*>() != nullptr) duration = 5;else if (light.state_cast<GreenState*>() != nullptr) duration = 4;else if (light.state_cast<YellowState*>() != nullptr) duration = 2;// 等待定时for (int i = 0; i < duration; ++i) {cout << "."; cout.flush();std::this_thread::sleep_for(std::chrono::seconds(1));}light.process_event(EvTimeout()); // 触发超时事件}
}int main() {TrafficLight light;light.initiate(); // 启动状态机(初始为红灯)// 启动运行线程std::thread t(run, std::ref(light));t.detach();// 处理紧急事件输入std::string input;while (std::cin >> input) {if (input == "e") light.process_event(EvEmergency());}return 0;
}

特点

  • 优点:库已封装状态管理、事件分发等复杂逻辑,支持嵌套状态、并行状态等高级特性,可靠性高。
  • 缺点:依赖第三方库,学习成本较高,可能引入不必要的复杂性(简单场景用不上)。
  • 适用场景:大型项目或需要高级特性(如并行状态、历史状态)的场景(如车载系统、工业控制软件)。
5. 有限状态机(FSM)工具生成的状态机

核心思想:通过可视化工具(如 Stateflow、Enterprise Architect)绘制状态图,自动生成代码(C/C++/Python 等),避免手动编码错误。
特点

  • 优点:可视化设计状态转换,自动生成规范代码,适合团队协作和复杂状态逻辑(如状态嵌套、并行分支)。
  • 缺点:依赖工具,生成的代码可能冗余,修改需通过工具重新生成。
  • 适用场景:大规模嵌入式系统、汽车电子(如自动驾驶状态逻辑)。
    面向对象状态机与设计模式中的状态模式(State Pattern) 既有联系又有区别,核心差异体现在范围、实现方式和设计目标上。下面详细解析两者的关系与区别:

三、状态机与状态模式的异同

1. 概念定义
  • 面向对象状态机(Object-Oriented State Machine)
    用面向对象(OOP)思想和技术实现的状态机,其核心是通过类、对象、继承、多态等OOP特性,将状态机的“状态”“事件”“转换规则”“行为”等元素封装为对象,以实现状态的管理和转换。
    它是一个宽泛的概念,只要符合“用OOP思想实现状态机”的逻辑,都可称为面向对象状态机。
  • 状态模式(State Pattern)
    是GoF(四人组)定义的23种设计模式之一(行为型模式),其核心思想是将对象的状态封装为独立的状态类,使对象在不同状态下的行为由对应的状态类处理,从而避免大量的条件判断(如if-elseswitch-case)。
    它是一种具体的设计模式,有明确的结构规范(环境类、抽象状态类、具体状态类)。
2. 相同点

状态模式本质上是面向对象状态机的典型实现方式
状态模式通过OOP的“封装”和“多态”特性,将状态的行为与转换逻辑封装到独立的状态类中,完全符合“面向对象状态机”的设计思想。因此,用状态模式实现的状态机,一定是面向对象状态机

3. 差异点
维度面向对象状态机状态模式(State Pattern)
范围宽泛概念:所有用OOP实现的状态机都属于此类具体模式:是面向对象状态机的一种特定实现
结构规范无固定结构,可灵活设计有严格结构:环境类(Context)+ 抽象状态类(State)+ 具体状态类(ConcreteState)
核心目标用OOP管理状态机的元素(状态、事件、转换)消除状态相关的条件判断,让状态行为更易维护
灵活性可简单可复杂(如用枚举+switch也属于OOP实现)必须通过状态类封装行为,灵活性更高(符合开闭原则)
适用场景状态较少、转换逻辑简单时可简化实现状态较多、行为复杂、频繁新增/修改状态时更适用
4. 具体差异示例(以红绿灯为例)
1. 非状态模式的面向对象状态机(仍属OOP实现)

用枚举定义状态,在环境类中通过switch-case处理状态转换(未用状态模式,但符合OOP思想):

// 枚举定义状态(OOP中的封装)
enum class TrafficLightState { RED, GREEN, YELLOW };class TrafficLight {
private:TrafficLightState currentState; // 状态作为对象成员(OOP特性)
public:TrafficLight() : currentState(TrafficLightState::RED) {}void nextState() {// 用switch处理状态转换(未用状态模式)switch (currentState) {case TrafficLightState::RED:currentState = TrafficLightState::GREEN;std::cout << "切换为绿灯\n";break;case TrafficLightState::GREEN:currentState = TrafficLightState::YELLOW;std::cout << "切换为黄灯\n";break;case TrafficLightState::YELLOW:currentState = TrafficLightState::RED;std::cout << "切换为红灯\n";break;}}
};
  • 这是面向对象状态机(用类、对象管理状态),但未使用状态模式(依赖switch判断状态)。
2. 状态模式实现的面向对象状态机

严格遵循状态模式结构,将状态行为封装到独立的状态类中:

// 抽象状态类(State)
class LightState {
public:virtual void nextState(TrafficLight* light) = 0; // 多态接口virtual ~LightState() = default;
};// 具体状态类:红灯
class RedState : public LightState {
public:void nextState(TrafficLight* light) override {light->setState(new GreenState()); // 转换为绿灯std::cout << "切换为绿灯\n";}
};// 具体状态类:绿灯、黄灯(类似RedState,略)// 环境类(Context)
class TrafficLight {
private:LightState* currentState; // 依赖抽象状态
public:TrafficLight() : currentState(new RedState()) {}void setState(LightState* state) {delete currentState;currentState = state;}void nextState() {currentState->nextState(this); // 委托给状态类处理}
};
  • 这是状态模式,同时也是面向对象状态机(用OOP的继承、多态实现)。
5. 总结
  • 状态模式是面向对象状态机的“子集”:状态模式是一种规范的、高灵活性的面向对象状态机实现方式。
  • 核心区别:面向对象状态机是“用OOP实现状态机”的统称,可简单可复杂;而状态模式是一种严格结构化的设计模式,专为解决“状态行为复杂、需避免条件判断”的问题而生。状态少、逻辑简单时,可用简单的面向对象状态机(如枚举+switch);状态多、行为复杂时,优先用状态模式(更易扩展和维护)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95086.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95086.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows 手动病毒排查指南:不依赖杀毒软件的系统安全防护

Windows 手动病毒排查指南&#xff1a;不依赖杀毒软件的系统安全防护 在数字时代&#xff0c;电脑病毒就像潜伏的"网络幽灵"&#xff0c;从窃取隐私的木马到消耗资源的蠕虫&#xff0c;时刻威胁着系统安全。当杀毒软件失效或遭遇新型威胁时&#xff0c;手动排查病毒便…

GPT-5 is here

GPT-5 is here https://openai.com/index/introducing-gpt-5/ — and it’s #1 across the board! #1 in Text, WebDev, and Vision Arena #1 in Hard Prompts, Coding, Math, Creativity, Long Queries, and more Tested under the codename “summit”, GPT-5 now holds the …

【华为机试】55. 跳跃游戏

文章目录55. 跳跃游戏题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a;解题思路一、问题本质与建模二、方法总览与选择三、贪心算法的正确性&#xff08;直观解释 循环不变式&#xff09;四、反向贪心&#xff1a;等价但有启发的视角五、与动态规划的对比与误区…

RabbitMQ面试精讲 Day 18:内存与磁盘优化配置

【RabbitMQ面试精讲 Day 18】内存与磁盘优化配置 开篇&#xff1a;内存与磁盘优化的重要性 欢迎来到"RabbitMQ面试精讲"系列的第18天&#xff01;今天我们将深入探讨RabbitMQ的内存与磁盘优化配置&#xff0c;这是面试中经常被问及的高频主题&#xff0c;也是生产环…

【C++】string 的特性和使用

Ciallo&#xff5e; (∠・ω< )⌒★ string&#xff08;1&#xff09;1. 构造函数1.1 string();1.2 string(const char* s);1.3 string(const string& str);1.4 string(size_t n, char c);1.5 string(const string& str, size_t pos, size_t len npos);1.6 string(…

创始人IP的精神修炼:于成长中积蓄力量

IP 经济席卷之下&#xff0c;众多企业家常被 “是否入局 IP”“能否做好 IP” 的焦虑裹挟。这种潜藏的精神内耗&#xff0c;对企业根基的侵蚀往往胜过业绩的起伏。著名文化学者于丹在全球创始人 IP 领袖高峰论坛上的洞见&#xff0c;为创始人 IP 的精神成长照亮了前路&#xff…

gbase8s数据库中对象元数据查询

最近整理了gbase8s数据库中常见的元数据的查询&#xff0c;包括表、视图、序列、包、类型、触发器、plsql等等&#xff0c;仅供参考。set environment sqlmode oracle; drop package DBMS_METADATA; create or replace package DBMS_METADATA is function GET_DDL(objtype varc…

常用hook钩子函数

爬虫Hook技术常用字段和勾子函数 目录 Hook技术概述网络请求相关Hook浏览器环境HookJavaScript引擎Hook加密算法Hook反爬虫检测Hook实际应用示例Hook工具和框架 Hook技术概述 Hook&#xff08;钩子&#xff09;技术是一种在程序运行时拦截和修改函数调用的技术。在爬虫中&a…

【解决方法】华为电脑的亮度调节失灵

华为电脑的亮度调节失灵 参考文章&#xff1a; 华为电脑屏幕亮度怎么调不了&#xff1f;华为电脑调节亮度没反应解决教程 亲测&#xff0c;在控制面板中卸载HWOSD&#xff0c;再重装有用。

【软考中级网络工程师】知识点之 DCC 深度剖析

目录一、DCC 是什么1.1 定义阐述1.2 作用讲解二、DCC 工作原理2.1 拨号触发机制2.1.1 感兴趣流量定义2.1.2 触发拨号过程2.2 链路建立流程2.2.1 物理链路连接2.2.2 数据链路层协议协商三、DCC 配置要点3.1 基础配置步骤3.1.1 接口配置3.1.2 拨号映射配置3.2 高级配置参数3.2.1 …

W5500之Socket寄存器区介绍

W5500之Socket寄存器区介绍1)、Socket n模式寄存器(Socket n Mode Register&#xff0c;简写Sn_MR)偏移地址为0x0000&#xff0c;可读写&#xff0c;复位值为0x00&#xff1b;Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0MULTI/MFENBCASTBND/MC/MMBUCASTB/MIP6BP3P2P1P0MULTI/MFEN占用“S…

酉矩阵(Unitary Matrix)和随机矩阵

先讨论酉矩阵&#xff08;Unitary Matrix&#xff09;的性质。1. 酉矩阵定义酉矩阵&#xff08;Unitary Matrix&#xff09;是复数域上的方阵&#xff0c;满足以下条件&#xff1a;其中&#xff1a;是 的共轭转置&#xff08;即 Hermitian 转置&#xff0c; &#xff09;。是单…

「iOS」————单例与代理

iOS学习单例代理代理模式的原理代理的循环引用设计模式单例 优点&#xff1a; 全局访问&#xff1a;单例模式确保一个类只有一个实例&#xff0c;并提供全局访问点&#xff0c;方便在整个应用中共享数据或功能。节省资源&#xff1a;由于只创建一个实例&#xff0c;可以减少内…

Microsoft Dynamics AX 性能优化解决方案

一、方案背景Microsoft Dynamics AX 是功能强大的企业ERP系统&#xff0c;虽然Microsoft 已推出基于云的现代化 ERP 平台 Dynamics 365 Finance and Operations&#xff0c;提供了更高的性能和持续更新&#xff0c;用来替代Dynamics AX。在考虑升级到Dynamics 365之前&#xff…

ARM保留的标准中断处理程序入口和外设中断处理程序入口介绍

在ARM架构中&#xff0c;中断处理是一个关键机制&#xff0c;它允许CPU在执行主程序时能够响应外部或内部的事件。对于ARM MCU&#xff08;微控制器单元&#xff09;而言&#xff0c;中断处理程序入口通常分为两类&#xff1a;ARM保留的标准中断处理程序入口和外设中断处理程序…

防火墙环境下的全网服务器数据自动化备份平台搭建:基于 rsync 的完整实施指南

一、项目总览 1.内容介绍 本文以 3 台 CentOS 7.9 服务器&#xff08;Web 服务器、NFS 服务器、备份服务器&#xff09;为载体&#xff0c;详解如何在全防火墙开启的前提下&#xff0c;搭建一套自动化数据备份平台&#xff1a;每日自动打包 Web 站点、NFS 共享数据及系统关键…

Spring之【Import】

目录 Import注解 源码分析 使用示例 ImportSelector 源码分析 使用示例 DeferredImportSelector 源码分析 使用示例 ImportBeanDefinitionRegistrar 源码分析 使用示例 Import注解 源码分析 处理组件类上的Import注解 将Import引入类对应的BeanDefinition对象添加…

RN项目环境搭建和使用-Mac版本(模拟器启动不起来的排查)

ReactNative&#xff1a; https://github.com/facebook/react-native https://reactnative.cn/docs/getting-started &#xff08;可以先通读一下这个&#xff09; 环境搭建 &#xff08;mac版&#xff09;https://juejin.cn/post/7404860612758765605 搭建之前确认版本&#x…

悬赏任务系统网站兼职赚钱小程序搭建地推抖音视频任务拉新源码功能详解二开

功能详解&#xff08;一&#xff09;登录与注册1、登录&#xff1a;打开系统用户端&#xff0c;输入已注册的手机号&#xff0c;若为首次登录或忘记密码&#xff0c;可通过 “找回密码” 功能&#xff0c;按提示验证身份后重置密码登录。 2、注册&#xff1a;点击 “注册” 按钮…

scikit-learn/sklearn学习|线性回归解读

【1】引言 前序学习进程中&#xff0c;对SVM相关的数学原理进行了探索和推导&#xff0c;相关文章链接包括且不限于&#xff1a; python学智能算法&#xff08;二十六&#xff09;|SVM-拉格朗日函数构造-CSDN博客 python学智能算法&#xff08;二十八&#xff09;|SVM-拉格朗…