用C++实现分层有限状态机

软文推广2个月前发布 刘老三
4 0

在软件工程中,有限状态机 (FSM) 是一种以结构化和有组织的方式建模和实现复杂行为的强大技术。 FSM 在实体可以存在于不同状态且其行为由其当前状态及其接收的事件确定的情况下特别有用。然而,随着系统变得更加复杂,传统的扁平 FSM 可能变得笨重且难以管理。这就是分层有限状态机 (HFSM) 发挥作用的地方。

HFSM 向 FSM 引入了层次结构,从而允许更好的组织、模块化和状态行为的可重用性。在这篇博文中,我们将深入研究 C++ 中成熟的 HFSM 的实现,涵盖状态转换管理、事件处理和状态嵌套等各个方面。

用C++实现分层有限状态机

了解 HFSM

在深入研究实现细节之前,我们先来了解一下 HFSM 的核心概念:

1.状态:与传统的 FSM 类似,HFSM 由表示实体可以存在的不同配置或模式的状态组成。

2.分层嵌套:在 HFSM 中,状态可以包含嵌套子状态,从而允许行为的分层组织。这种嵌套可以是任意深度,从而能够表示复杂的行为模式。

3.状态转换:状态之间的转换由事件触发,就像传统的 FSM 一样。然而,在 HFSM 中,转换不仅可以发生在兄弟状态之间,还可以发生在父状态和子状态之间,从而实现更灵活的行为建模。

4.进入和退出操作:每个状态都可以有与其关联的进入和退出操作。这些操作分别在进入或退出状态时执行,从而允许初始化和清理操作。

有了这样的理解,让我们深入研究 C++ 中 HFSM 的实现。

HFSM 实施

我们的 HFSM 实现将包含几个类:

1.State:代表 HFSM 中的单个状态。

2.StateMachine:管理整体状态机,包括状态转换和事件处理。

3.Context:封装与 HFSM 相关的上下文或数据,可以由状态访问和修改。

1.State班级

该类State是我们 HFSM 的构建块。它代表一个单独的状态及其相关的行为。

#include <functional>
#include <memory>
#include <unordered_map>
#include <vector>

class StateMachine; // Forward declaration

class State {
public:
using ActionCallback = std::function<void()>;
using TransitionCallback = std::function<void(StateMachine&)>;

State(const std::string& name);

void setEntryAction(const ActionCallback& action);
void setExitAction(const ActionCallback& action);

void addTransition(const std::string& event, const std::string& targetState, const TransitionCallback& action = nullptr);
void addNestedState(const std::shared_ptr<State>& state);

const std::string& getName() const;
void activate(StateMachine& machine);
void deactivate(StateMachine& machine);

private:
std::string name;
ActionCallback entryAction;
ActionCallback exitAction;
std::unordered_map<std::string, std::pair<std::string, TransitionCallback>> transitions;
std::vector<std::shared_ptr<State>> nestedStates;

friend class StateMachine;
};

该类State提供了用于设置进入和退出操作、添加转换和嵌套状态以及在StateMachine.ActionCallback和类型TransitionCallback是分别用于表示操作和转换回调的函数对象类型。

2.StateMachine班级

该类StateMachine管理整个 HFSM,处理状态转换和事件处理。

#include <memory>
#include <stack>
#include <string>
#include <unordered_map>

class State;

class StateMachine {
public:
StateMachine(std::shared_ptr<State> initialState);

void processEvent(const std::string& event);
void setContext(const std::shared_ptr<Context>& context);

private:
std::shared_ptr<State> currentState;
std::stack<std::shared_ptr<State>> stateStack;
std::unordered_map<std::string, std::shared_ptr<State>> states;
std::shared_ptr<Context> context;

void changeState(const std::shared_ptr<State>& newState, const State::TransitionCallback& action);
};

该类StateMachine在构造期间采用初始状态,并提供processEvent处理传入事件的方法。它还维护一个状态堆栈来处理分层状态转换,以及一个所有注册状态的映射以进行高效查找。

3.Context班级

该类Context封装了与 HFSM 相关的数据或上下文,可以由状态访问和修改。

class Context {
public:
// Define your context data and methods here
// For example:
int someData;
void modifyData(int value);
};

该类的具体实现Context将取决于您的 HFSM 的要求及其需要管理的数据。

4. HFSM 类的实现

State以下是和类的实现StateMachine:

// State.cpp
#include “State.h”
#include “StateMachine.h”

State::State(const std::string& name)
: name(name) {}

void State::setEntryAction(const ActionCallback& action) {
entryAction = action;
}

void State::setExitAction(const ActionCallback& action) {
exitAction = action;
}

void State::addTransition(const std::string& event, const std::string& targetState, const TransitionCallback& action) {
transitions[event] = std::make_pair(targetState, action);
}

void State::addNestedState(const std::shared_ptr<State>& state) {
nestedStates.push_back(state);
}

const std::string& State::getName() const {
return name;
}

void State::activate(StateMachine& machine) {
if (entryAction) {
entryAction();
}

for (const auto& nestedState : nestedStates) {
nestedState->activate(machine);
}
}

void State::deactivate(StateMachine& machine) {
for (const auto& nestedState : nestedStates) {
nestedState->deactivate(machine);
}

if …e.h”

StateMachine::StateMachine(std::shared_ptr<State> initialState)
: currentState(initialState) {
states[initialState->getName()] = initialState;
currentState->activate(*this);
stateStack.push(currentState);
}

void StateMachine::processEvent(const std::string& event) {
const auto& transitions = currentState->transitions;
auto it = transitions.find(event);

if (it != transitions.end()) {
const auto& [targetState, action] = it->second;
auto newState = states[targetState];
changeState(newState, action);
}
}

void StateMachine::setContext(const std::shared_ptr<Context>& context) {
this->context = context;
}

void StateMachine::changeState(const std::shared_ptr<State>& newState, const State::TransitionCallback& action) {
if (action) {
action(*this);
}

currentState->deactivate(*this);
stateStack.pop();

currentState = newState;
stateStack.push(currentState);
currentState->activate(*this);
}

5. 使用 HFSM

现在我们已经实现了 HFSM 类,让我们看看如何使用它们来建模和执行简单的分层状态机。

让我们考虑一个交通灯控制器的简单示例。交通信号灯可以存在三种主要状态:Red、Green和Yellow。此外,该Green状态可以具有嵌套BlinkingGreen状态,该状态表示转换到该状态之前闪烁的绿灯Yellow。

#include <iostream>
#include <memory>

#include “State.h”
#include “StateMachine.h”
#include “Context.h”

int main() {
// Define the context
std::shared_ptr<Context> context = std::make_shared<Context>();

// Define the states
std::shared_ptr<State> redState = std::make_shared<State>(“Red”);
std::shared_ptr<State> greenState = std::make_shared<State>(“Green”);
std::shared_ptr<State> yellowState = std::make_shared<State>(“Yellow”);
std::shared_ptr<State> blinkingGreenState = std::make_shared<State>(“BlinkingGreen”);

// Set entry and exit actions
redState->setEntryAction([]() { std::cout << “Red light on” << std::endl; });
greenState->setEntryAction([]() { std::cout << “Green light on” << std::endl; });
yellowState->setEntryAction([]() { std::cout << “Yellow light on” << std::endl; });
blinkingGreenState->setEntryAction([]() { std::cout << “Blinking green light” << std::endl; });

// Add transitions
redState->addTransition(“next”, “Green”);
greenState->addTransition(“next”, “BlinkingGreen”);
blinkingGreenState->addTransition(“next”, “Yellow”);
yellowState->addTransition(“next”, “Red”);

// Add nested state
greenState->addNestedState(blinkingGreenState);

// Create the state machine
std::shared_ptr<StateMachine> trafficLight = std::make_shared<StateMachine>(redState);
trafficLight->setContext(context);

// Process events
trafficLight->processEvent(“next”);
trafficLight->processEvent(“next”);
trafficLight->processEvent(“next”);
trafficLight->processEvent(“next”);

return 0;
}

在此示例中,我们定义Red、Green、Yellow和BlinkingGreen状态,设置它们的进入操作,并在它们之间添加转换。该BlinkingGreen状态作为状态的嵌套状态添加Green。

然后,我们创建一个StateMachine将该Red状态作为初始状态的实例,并处理一系列“下一个”事件,这会触发状态转换。

当您运行该程序时,您应该看到以下输出:

Red light on
Green light on
Blinking green light
Yellow light on
Red light on

此输出演示了状态机的分层性质,其中状态在转换到状态之前BlinkingGreen作为状态的嵌套状态被激活。GreenYellow

6. 高级功能和注意事项

到目前为止,我们介绍的实现为用 C++ 构建 HFSM 奠定了坚实的基础。但是,您可能需要进一步探索一些高级功能和注意事项:

1.状态历史记录:实现对状态历史记录的支持,允许 HFSM 在重新进入父状态时记住以前的活动状态。

2.事件过滤器:实现事件过滤器来控制特定状态或状态层次结构处理哪些事件。

3.状态正交性:支持正交状态,其中多个并行状态机在同一上下文中独立运行。

4.保护条件:在转换上实现保护条件,以基于当前上下文或状态启用更复杂的转换逻辑。

5.状态并发:支持并发状态,其中多个状态可以在同一层次结构中同时处于活动状态。

6.事件队列:实现事件队列来处理 HFSM 在状态转换过程中发生的事件。

7.状态序列化和反序列化:实现对状态机的配置和当前状态进行序列化和反序列化的机制,从而实现状态持久化和恢复。

这些高级功能可以帮助您创建适合您的特定用例的更复杂、更强大的 HFSM。

结论

在这篇文章中,我们探索了 C++ 中成熟的分层有限状态机的实现。我们介绍了 HFSM 的核心概念,实现了State和StateMachine类,并通过一个简单的交通灯控制器示例演示了它们的用法。

HFSM 提供了强大且结构化的方法来建模复杂行为,促进代码组织、模块化和可重用性。通过利用 HFSM 的分层性质,您可以有效地管理和推理系统的行为,从而更轻松地开发、维护和扩展应用程序。

虽然我们介绍的实现提供了坚实的基础,但您可能需要进一步探索一些高级功能和注意事项,例如状态历史记录、事件过滤器、状态正交性、保护条件、状态并发、事件队列和状态序列化/反序列化。

在 C++ 中实现 HFSM 可能是一项有益且具有挑战性的工作,但改进的代码结构、可维护性和行为建模的好处使其成为一项值得掌握的有价值的技术。当您继续 HFSM 之旅时,请记住调整和扩展实施以满足您的特定要求,并利用分层状态机的强大功能来创建强大且可扩展的软件系统。

© 版权声明

相关文章