Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 简单状态转换的状态机方法_Java_State_State Machine_State Pattern - Fatal编程技术网

Java 简单状态转换的状态机方法

Java 简单状态转换的状态机方法,java,state,state-machine,state-pattern,Java,State,State Machine,State Pattern,我正在研究创建一个非常简单的状态机。我的状态机将包含以下3种状态: public enum States { PENDING, ACTIVE, DONE } 这里可能存在多个转换+启动状态,具体来说: 初始状态:挂起或活动 过渡: PENDING->ACTIVE PENDING->DONE ACTIVE->DONE 我正在研究表示这些状态的方法和控制转换的可能状态机。我已经研究了一种基于枚举的方法,例如,但我还想向客户端公开状态转换,我不确定这种方法是否合理 我还研究了

我正在研究创建一个非常简单的状态机。我的状态机将包含以下3种状态:

public enum States {
    PENDING,
    ACTIVE,
    DONE
}
这里可能存在多个转换+启动状态,具体来说:

初始状态:
挂起或活动
过渡:

  • PENDING->ACTIVE
  • PENDING->DONE
  • ACTIVE->DONE
  • 我正在研究表示这些状态的方法和控制转换的可能状态机。我已经研究了一种基于枚举的方法,例如,但我还想向客户端公开状态转换,我不确定这种方法是否合理

    我还研究了其他技术,如,但对于这样一个简单的问题来说,这可能有些过头了


    有人对满足这个标准的简单状态机实现有什么建议吗?我甚至在想一些基本的事情,比如使用转换表来存储转换,并在其中封装状态概念,使用转换表来确定下一个可能的状态。

    其中一个简单的变体是以
    的形式保存转换,我想在应用此转换时从X转换到Y功能
    。枚举非常适合枚举状态机中所有可能/有效的状态。我们需要一些东西来保持我们的状态转换-也许是一个
    映射
    ?但是我们还需要某种类型的
    状态
    对象和修改它的方法-我们需要一个
    映射
    。请参阅下面的一些编译示例代码,这些代码将帮助您开始。您可以随意公开
    状态
    对象(可能使其不可变?),并动态添加转换

    import java.util.EnumMap;
    import java.util.Map;
    import java.util.function.Function;
    
    class StackOverflowQuestion57661787 {
        enum StateType {
            PENDING,
            ACTIVE,
            DONE
        }
    
        //Made the name explicit here to ease readability
        public interface Transition extends Function<State, State> { }
    
        public static class State {
            public StateType type;
            //TODO: some real data to manipulate, or make it immutable
            public Object data;
        }
    
        public static class StateMachine {
            private final Map<StateType, Map<StateType, Transition>> transitions =
                    new EnumMap<>(StateType.class);
            private State state;
    
            public StateMachine(State initialState) {
                this.state = initialState;
                for (StateType value : StateType.values()) {
                    transitions.put(value, new EnumMap<>(StateType.class));
                }
            }
    
            public void addTransition(
                    StateType input,
                    StateType output,
                    Transition transition
            ) {
                //TODO: handle collisions? multiple transitions for a given 
                // output statetype seems like a strange use-case
                transitions.get(input).put(output, transition);
            }
    
            public void moveTo(StateType toType) {
                Transition transition = transitions.get(state.type).get(toType);
                if (transition == null) {
                    //TODO: handle me
                    throw new RuntimeException();
                }
                //transition should modify the states "type" too OR
                //you implement it here
                state = transition.apply(state);
            }
    
            public State getState() {
                return state;
            }
        }
    }
    
    import java.util.EnumMap;
    导入java.util.Map;
    导入java.util.function.function;
    类堆栈溢出问题57661787{
    枚举状态类型{
    悬而未决的
    活跃的,
    完成
    }
    //在此处明确了名称,以便于阅读
    公共接口转换扩展函数{}
    公共静态类状态{
    公共状态类型;
    //TODO:一些实际数据需要操作,或使其不可变
    公共对象数据;
    }
    公共静态类状态机{
    私有最终映射转换=
    新的EnumMap(StateType.class);
    私营国家;
    公共状态机(状态初始状态){
    this.state=初始状态;
    for(StateType值:StateType.values()){
    transitions.put(值,新枚举映射(StateType.class));
    }
    }
    公共空间转换(
    状态类型输入,
    状态类型输出,
    过渡
    ) {
    //TODO:处理冲突?给定时间的多个转换
    //输出状态类型似乎是一个奇怪的用例
    转换.get(输入).put(输出,转换);
    }
    public void moveTo(StateType toType){
    Transition Transition=transitions.get(state.type).get(toType);
    if(transition==null){
    //托多:对付我
    抛出新的RuntimeException();
    }
    //转换也应修改状态“类型”,或
    //你在这里实现它
    状态=转换。应用(状态);
    }
    公共状态getState(){
    返回状态;
    }
    }
    }
    

    你必须达到一个更复杂的抽象的解决方案,如果你的代码>状态< /代码>对象类型依赖于当前<代码> Stestype < /C> >

    < P>如果你使用Spring,你可以考虑Spring StaseMaCHIN。
    我有一个我广泛使用的个人设计,我称之为“泵”。您的状态机类有一个名为“pump”的函数,该函数计算状态并相应更新。每个状态评估可能需要来自外部源(控制器)的一些输入,如用户或AI。这些对象在初始化状态机时是必需的,通常是抽象实现。然后添加应用程序可以覆盖以捕获事件的事件回调。这种方法的一个优点是“泵”方法可以从单线程或多线程系统执行

    一旦您的机器建成,您就可以轻松地进行单元测试,只需调用pump forever并提供返回随机值的控制器。这将是一个有效的“猴子”测试,以确保您的机器可以处理任何输入组合而不会崩溃

    然后在应用程序中,您只需要根据情况提供适当的控制器

    下面是一个非常粗糙的状态机来控制一个假想的骰子游戏。我省略了大部分细节,留下了方法的要点。请注意,Player.rollDice的一个实现可能是一个阻塞方法,它等待用户点击按钮来推进游戏。在这个方案中,控制游戏的所有逻辑都包含在机器中,可以独立于任何UI进行测试

    interface Player {
       boolean rollDice();
    }
    
    class Game {
       int state;
       Player [] players;
       int currentPlayer;
       int dice;
    
       void pump() {
          switch (state) {
             case ROLL_DICE:
                if (players[currentPlayer].rollDice()) {
                   dice = Math.rand() % 6 + 1;
                   onDiceRolled(dice);
                   state = TAKE_TURN;
                }
                break;
             case TAKE_TURN:
                ...
                break;
          }
       }
    
       // base method does nothing. Users can override to handle major state transitions.
       protected void onDiceRolled(int dice) {}
    }
    

    谢谢-这是非常有用的。你可以使用spring状态机非常整洁和易于使用