【问题标题】:An FSM with object state in JavaJava中具有对象状态的FSM
【发布时间】:2013-08-28 09:06:16
【问题描述】:

我正在 java 类中实现一个有限状态机。我无法找到另一个将状态和事件作为它们自己的对象的示例(也许这是有原因的?),而且我不太相信我的解决方案,特别是因为我必须为 FSM 分配一个状态(实际管理者)然后将 FSM 分配给状态(以通知状态更改)。这是状态管理器的代码,我为其分配了一个状态,并在被要求时将其吐出:

public class FSM {

    public void setCurrentState(FSMState newCurrentState) {
        this.currentState = newCurrentState;
    }

    private FSMState currentState;

    public FSMState getCurrentState() {
        if (this.currentState == null)
            System.out.println("No current state");
        return this.currentState;
    }
}

这是状态,它使用映射将事件映射到输出状态,并在发生转换时通知 FSM 类:

public class FSMState implements EventListener {

    private FSM managingFSM;
    private Map<Event,FSMState> transitions;

    public FSMState(FSM managingFSM) {
        this.transitions = new HashMap<Event, FSMState>();
        this.managingFSM = managingFSM;
    }

    public void addEventTransition(Event event, FSMState outputState){
        transitions.put(event, outputState);
        event.registerListener(this);
    }

    @Override
    public void eventOccured(Event e) {
        FSMState newState = transitions.get(e);
        this.managingFSM.setCurrentState(newState);
    }
}

有没有办法,用一种类似的解决方案,让国家不必通知经理?

【问题讨论】:

  • 这看起来很容易出错。什么时候向 FSMStates 添加事件转换?因为按照您现在所做的方式,当事件发生时,它将在它注册的任何 FSMState 中触发(无论当前状态是什么)并更改当前状态。我猜您只想触发当前状态的事件,以便获得正确的转换。

标签: java oop fsm state-machine


【解决方案1】:

我会说您的实现需要进行很多更改。首先,您可能希望在创建 FSM 本身之前创建状态及其转换。我会创建一个单独的类来管理名为 FSMManager 的初始化和设置。

首先将 FSMState 更改为:

public class FSMState {

    private Map<Event,FSMState> transitions;

    public FSMState() {
        this.transitions = new HashMap<Event, FSMState>();
    }

    public void addEventTransition(Event event, FSMState outputState){
        transitions.put(event, outputState);
    }

    public FSMState transition(Event e) {
        if(transitions.containsKey(e)) {
            return transitions.get(e);
        }
        else {
            System.out.println("No transition found");
            return this;
        }
    }

}

然后将 FSM 类更改为如下所示:

public class FSM implements EventListener {

    private FSMState currentState;

    public FSM(FSMState startState) {
        currentState = startState;
    }

    public FSMState getCurrentState() {
        if (this.currentState == null)
            System.out.println("No current state");
        return this.currentState;
    }

    @Override
    public void eventOccured(Event e) {
        currentState = currentState.transition(e);
    }
}

最后添加管理器来初始化一切:

public class FSMManager {

    private static final NUM_STATES = 5;

    public static void main(String[] args) {

         FSMState[] states = new FSMState[NUM_STATES];

         for(FSMState state : states) {
             state = new FSMState();
         }

         // Then add all the state transitions to all the states
         states[0].addEventTransition(event1, states[1]);
         states[1].addEventTransition(event1, states[2]);
         states[1].addEventTransition(event2, states[4]);
         // etc, etc

         //Finally, create the FSM
         FSM fsm = new FSM(state[0]);

         //You will also have to register the FSM to listen for all the events
         event1.registerListener(fsm);
         event2.registerListener(fsm);
         ...


    }

}

我不知道您从哪里获得所有 Events 以及它们实际上是如何被解雇的,但上述模式是一个很好的模式。这样,当一个事件被触发时,它只会应用于当前状态。相同的事件会在不同的状态下产生不同的转换,就像在状态机中一样。

这个解决方案应该会有所帮助,但它并不完美,因为我不知道你是如何做到这一点的,所以如果你有任何问题/进一步的问题发表评论,我会努力改进我的答案。

【讨论】:

    猜你喜欢
    • 2011-04-16
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多