代码之家  ›  专栏  ›  技术社区  ›  Stewart

状态机、封装和OOP设计

  •  0
  • Stewart  · 技术社区  · 6 年前

    我正在使用 Boost's MSM library .

    在FSM中,我有描述 事件 S, 来源 州, 目标 州, 行动 S和 警卫 S.

    这是我第一次使用更高级的状态机设计。在过去,我只是使用开关语句并执行代码。然而,这一个将是大,我想保持一切正常的组织,使它不会变成一个混乱。

    我有一个表示状态机的对象(它是 boost::msm::back::state_machine<MyStateMachine> 在哪里? MyStateMachine 是我继承自 boost::msm::front::state_machine_def )。

    诀窍是我的业务逻辑将在 行动 我认为这对金融服务管理来说并不少见。 Boost's examples 似乎暗示这些 行动 应该在状态机本身中作为方法实现,但我认为这可能会使一个类太大。我觉得把工作和状态机分开是有意义的。

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

    1. 在fsm类的方法中执行业务逻辑(我担心这会将状态管理与工作混合得太紧密)。

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

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

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

    5. 还有别的。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Takatoshi Kondo    6 年前

    your_app

    sm_

    sm_def

    your_app::process_event() your_app::handle_some()

    #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