【问题标题】:State machines, encapsulation and OOP design状态机、封装和 OOP 设计
【发布时间】:2018-12-19 23:26:48
【问题描述】:

我正在使用 Boost's MSM library 实现 FSM。

在 FSM 中,我有描述 事件状态、目标状态、动作的转换表>s 和 Guards。

这是我第一次使用更高级别的状态机设计。过去,我只是使用 switch 语句和执行代码。但是,这个会很大,我想让所有的东西都井井有条,这样它就不会变成一团糟。

我有一个代表状态机的对象(它是一个boost::msm::back::state_machine<MyStateMachine>,其中MyStateMachine 是我的实现,它继承自boost::msm::front::state_machine_def)。

诀窍是我的业务逻辑将在 Action 中完成。我认为这对于 FSM 来说并不少见。 Boost's examples 似乎建议这些 Actions 应该作为状态机本身的方法来实现,但我认为这可能会使一个类过于庞大。我觉得把工作和状态机分开是有意义的。

保持可读、可维护和可扩展的设计更有意义?

  1. 在 FSM 类的方法中执行业务逻辑(我担心这会将状态管理与工作混为一谈)。

  2. 在实例化 FSM 的父级中执行业务逻辑。 FSM 需要一个指向父级的指针,并且父级需要实现一个 FSM 可以理解的接口(或者 FSM 实现需要#include 父级的声明)。

  3. 在 FSM 实例化和拥有的新类中执行业务逻辑。

  4. 在新类中执行业务逻辑,该类由父类实例化并拥有,但作为引用(或指针)传递给 FSM。

  5. 别的东西。

【问题讨论】:

    标签: oop fsm


    【解决方案1】:

    这取决于您的情况,但我通常使用一种方法。

    也许它是 2 或 5 的变体。

    假设your_app 有您的业务逻辑。它需要表现得像状态机。我认为这是状态机的典型用例之一。

    在这种情况下,状态机可以作为your_app 的嵌套类放置。 your_app 有成员变量sm_,状态机实例。

    状态机的定义是sm_def。它有your_app 的引用。

    your_app 之外的人想要处理事件时,请致电your_app::process_event()。如果不想提供直接的事件处理接口,可以包装成your_app::handle_some()。如果您这样做,your_app::process_event() 应该是私有的。

    这里是示例实现:

    #include <iostream>
    #include <boost/msm/back/state_machine.hpp>
    
    #include <boost/msm/front/state_machine_def.hpp>
    #include <boost/msm/front/functor_row.hpp>
    
    namespace msm = boost::msm;
    namespace msmf = boost::msm::front;
    namespace mpl = boost::mpl;
    
    
    // application domain
    class your_app {
    public:
        your_app() :sm_(boost::ref(*this)) {
            sm_.start(); // start state machine
        }
    
        // public interface for event processing
    
        // Event definitions
        struct Event1 {
            int param;
        };
    
        template <typename Event>
        void process_event(Event const& ev) {
            sm_.process_event(ev);
        }
    
        void handle_some(int param) {
            process_event(Event1 {param});
        }
    private:
    
        // internal business logic triggered from the state machine
        void do_some_business(int param) {
            std::cout << "do_some_business " << param << std::endl;
        }
    
        // state machine definiition
        struct sm_def:msmf::state_machine_def<sm_def> {
            sm_def(your_app& ya):ya_(ya) {}
            // States
            struct State1:msmf::state<> {
                template <class Event,class Fsm>
                void on_entry(Event const&, Fsm&) {
                    std::cout << "State1::on_entry()" << std::endl;
                }
                template <class Event,class Fsm>
                void on_exit(Event const&, Fsm&) {
                    std::cout << "State1::on_exit()" << std::endl;
                }
            };
            struct State2:msmf::state<> {
                template <class Event,class Fsm>
                void on_entry(Event const&, Fsm&) {
                    std::cout << "State2::on_entry()" << std::endl;
                }
                template <class Event,class Fsm>
                void on_exit(Event const&, Fsm&) {
                    std::cout << "State2::on_exit()" << std::endl;
                }
            };
    
            // Set initial state
            typedef State1 initial_state;
    
            // Actions
            struct Action {
                template <class Event, class Fsm, class SourceState, class TargetState>
                void operator()(Event const& e, Fsm& f, SourceState&, TargetState&) const {    
                    // get your_app via Fsm.
                    f.ya_.do_some_business(e.param);
                }
            };
    
            // Transition table
            struct transition_table:mpl::vector<
                //          Start   Event   Next    Action  Guard
                msmf::Row < State1, Event1, State2, Action, msmf::none >,
                msmf::Row < State2, Event1, State1, Action, msmf::none >
            > {};
    
            your_app& ya_;
        };
    
        friend class sm; // give the friend access to the sm
        typedef msm::back::state_machine<sm_def> sm;
    
        sm sm_;
    };
    
    int main() {
        your_app ya;
    
        ya.process_event(your_app::Event1{42});
        ya.handle_some(44);
    }
    

    并运行演示:https://wandbox.org/permlink/PQGSGr0bnJHgaMpD

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 2014-10-20
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多