ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

FSM

2022-04-20 01:03:26  阅读:156  来源: 互联网

标签:String void transition FSM state public


package com.mrsaber.fsm;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.*;

public class FSM { // This class implements a Flying Spaghetti Monster


    public static void main(String[] args) {
        FSM fsm = new FSM("状态转换机器");
        fsm.addState("INIT");
        fsm.addState("PROCESSING");
        fsm.addState("FINISH");

        Transition toProcessing = new Transition("DO_WORK","INIT","PROCESSING"){
            @Override
            public void doBeforeTransition() {

            }

            @Override
            public void doAfterTransition() {
                System.out.println("DoAfter");
            }
        };
        System.out.println(fsm.currentState);
        fsm.addTransition(toProcessing);
        fsm.addEvent("DO_WORK");

    }

    protected String name;
    protected String currentState;
    protected Map<String, State> states;
    protected List<ChangeListener> changeListeners;
    protected boolean debug;

    /**
     * Create a blank FSM with the given name (which is arbitrary).
     */
    public FSM(String name) {
        this.name = name;
        this.states = new HashMap<String, State>();
        this.currentState = null;
        this.changeListeners = new ArrayList<ChangeListener>();
    }

    /**
     * Turn debugging on/off.
     */
    public void setDebugMode(boolean debug) {
        this.debug = debug;
    }

    /**
     * Report the current state of the finite state machine.
     */
    public String getState() {
        return currentState;
    }

    /**
     * Adds a new state with no entry or exit code.
     */
    public void addState(String state) {
        addState(state, null, null, null);
    }

    /**
     * Establish a new state the FSM is aware of. If the FSM does not currently
     * have any states, this state becomes the current, initial state. This is
     * the only way to put the FSM into an initial state.
     *
     * The entryCode, exitCode, and alwaysRunCode are Runnables that the FSM
     * executes during the course of a transition. entryCode and exitCode are
     * run only if the transition is between two distinct states (i.e. A->B
     * where A != B). alwaysRunCode is executed even if the transition is
     * re-entrant (i.e. A->B where A = B).
     **/
    public void addState(String state, Runnable entryCode, Runnable exitCode,
                         Runnable alwaysRunCode) {
        boolean isInitial = (states.size() == 0);
        if (!states.containsKey(state)) {
            states.put(state, new State(entryCode, exitCode, alwaysRunCode));
        }
        if (isInitial) {
            setState(state);
        }
    }

    public void setStateEntryCode(String state, Runnable entryCode) {
        states.get(state).entryCode = entryCode;
    }

    public void setStateExitCode(String state, Runnable exitCode) {
        states.get(state).exitCode = exitCode;
    }

    public void setStateAlwaysRunCode(String state, Runnable alwaysRunCode) {
        states.get(state).alwaysRunCode = alwaysRunCode;
    }

    /**
     * There are cases where a state is meant to be transitional, and the FSM
     * should always immediately transition to some other state. In those cases,
     * use this method to specify the start and end states. After the startState
     * has fully transitioned (and any change events have been fired) the FSM
     * will check to see if there is another state that the FSM should
     * automatically transition to. If there is one, addEvent(endState) is
     * called.
     *
     * Note: this creates a special transition in the lookup table called
     * "(auto)".
     */
    public void setAutoTransition(String startState, String endState) {
        // if (debug) {
        // Debug.out("FSM", "Establishing auto transition for " + startState +
        // " -> " + endState);
        // }
        states.get(startState).autoTransitionState = endState;
        addTransition(new Transition("(auto)", startState, endState));
    }

    /**
     * Sets the current state without following a transition. This will cause a
     * change event to be fired.
     */
    public void setState(String state) {
        setState(state, true);
    }

    /**
     * Sets the current state without followign a transition, and optionally
     * causing a change event to be triggered. During state transitions (with
     * the 'addEvent' method), this method is used with the triggerEvent
     * parameter as false.
     *
     * The FSM executes non-null runnables according to the following logic,
     * given start and end states A and B:
     *
     * <ol>
     * <li>If A and B are distinct, run A's exit code.</li>
     * <li>Record current state as B.</li>
     * <li>Run B's "alwaysRunCode".</li>
     * <li>If A and B are distinct, run B's entry code.</li>
     * </ol>
     */
    public void setState(String state, boolean triggerEvent) {
        boolean runExtraCode = !state.equals(currentState);
        if (runExtraCode && currentState != null) {
            states.get(currentState).runExitCode();
        }
        currentState = state;
        states.get(currentState).runAlwaysCode();
        if (runExtraCode) {
            states.get(currentState).runEntryCode();
        }
        if (triggerEvent) {
            fireChangeEvent();
        }
    }

    /**
     * Establish a new transition. You might use this method something like
     * this:
     *
     * fsm.addTransition(new FSM.Transition("someEvent", "firstState",
     * "secondState") { public void doBeforeTransition() {
     * System.out.println("about to transition..."); } public void
     * doAfterTransition() { fancyOperation(); } });
     */
    public void addTransition(Transition trans) {
        State st = states.get(trans.startState);
        if (st == null) {
            throw new NoSuchElementException("Missing state: "
                    + trans.startState);
        }
        st.addTransition(trans);
    }

    /**
     * Add a change listener -- this is a standard java change listener and is
     * only used to report changes that have already happened. ChangeEvents are
     * only fired AFTER a transition's doAfterTransition is called.
     */
    public void addChangeListener(ChangeListener cl) {
        if (!changeListeners.contains(cl)) {
            changeListeners.add(cl);
        }
    }

    /**
     * Feed the FSM with the named event. If the current state has a transition
     * that responds to the given event, the FSM will performed the transition
     * using the following steps, assume start and end states are A and B:
     *
     * <ol>
     * <li>Execute the transition's "doBeforeTransition" method</li>
     * <li>Run fsm.setState(B) -- see docs for that method</li>
     * <li>Execute the transition's "doAfterTransition" method</li>
     * <li>Fire a change event, notifying interested observers that the
     * transition has completed.</li>
     * <li>Now firmly in state B, see if B has a third state C that we must
     * automatically transition to via addEvent(C).</li>
     * </ol>
     */
    public void addEvent(String evtName) {
        State state = states.get(currentState);
        if (state.transitions.containsKey(evtName)) {
            Transition trans = state.transitions.get(evtName);
            // if (debug) {
            // Debug.out("FSM", "Event: " + evtName + ", " + trans.startState +
            // " --> " + trans.endState);
            // }
            trans.doBeforeTransition();
            setState(trans.endState, false);
            trans.doAfterTransition();
            fireChangeEvent();
            if (states.get(trans.endState).autoTransitionState != null) {
                // if (debug) {
                // Debug.out("FSM", "Automatically transitioning from " +
                // trans.endState + " to "
                // + states.get(trans.endState).autoTransitionState);
                // }
                addEvent("(auto)");
            }
        }
    }

    /**
     * Fire a change event to registered listeners.
     */
    protected void fireChangeEvent() {
        ChangeEvent changeEvent = new ChangeEvent(this);
        for (ChangeListener cl : changeListeners) {
            cl.stateChanged(changeEvent);
        }
    }

    /**
     * Represents a state with some number of associated transitions.
     */
    private static class State {
        Map<String, Transition> transitions;
        String autoTransitionState;
        Runnable entryCode;
        Runnable exitCode;
        Runnable alwaysRunCode;

        State(Runnable entryCode, Runnable exitCode, Runnable alwaysRunCode) {
            autoTransitionState = null;
            transitions = new HashMap<String, Transition>();
            this.entryCode = entryCode;
            this.exitCode = exitCode;
            this.alwaysRunCode = alwaysRunCode;
        }

        public void addTransition(Transition trans) {
            transitions.put(trans.evtName, trans);
        }

        public void runEntryCode() {
            if (entryCode != null) {
                entryCode.run();
            }
        }

        public void runExitCode() {
            if (exitCode != null) {
                exitCode.run();
            }
        }

        public void runAlwaysCode() {
            if (alwaysRunCode != null) {
                alwaysRunCode.run();
            }
        }
    }

    /**
     * Create a new transition. See the documentation for addEvent and
     * addTransition in FSM.
     */
    public static class Transition {
        String evtName;
        String startState;
        String endState;

        /**
         * Create a transition object that responds to the given event when in
         * the given startState, and puts the FSM into the endState provided.
         */
        public Transition(String evtName, String startState, String endState) {
            this.evtName = evtName;
            this.startState = startState;
            this.endState = endState;
        }

        /**
         * Override this to have FSM execute code immediately before following a
         * state transition.
         */
        public void doBeforeTransition() {
        }

        /**
         * Override this to have FSM execute code immediately after following a
         * state transition.
         */
        public void doAfterTransition() {
        }
    }
}

 

标签:String,void,transition,FSM,state,public
来源: https://www.cnblogs.com/MrSaver/p/16168141.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有