亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用于簡單狀態轉換的狀態機方法

用于簡單狀態轉換的狀態機方法

翻閱古今 2023-06-21 14:42:51
我正在研究創建一個非常簡單的狀態機。我的狀態機將包含以下 3 個狀態:public?enum?States?{ ????PENDING, ????ACTIVE, ????DONE }這里可能有多個轉換+起始狀態,具體來說:初始狀態:PENDING or ACTIVE?轉換:PENDING -> ACTIVEPENDING -> DONEACTIVE -> DONE我正在研究表示這些狀態的方法以及控制轉換的可能狀態機。我研究了一種基于枚舉的方法,但我也想向客戶端公開狀態轉換,并且我不確定這種方法是否合理。我也看過其他技術,例如State Pattern,但感覺對于這樣一個簡單的問題來說這可能有點矯枉過正。有人對滿足此標準的簡單狀態機實現有任何建議嗎?我什至在考慮一些基本的事情,例如使用轉換表來存儲轉換并在其中封裝一個狀態概念,該狀態概念將使用轉換表來確定下一個可能的狀態。
查看完整描述

3 回答

?
侃侃爾雅

TA貢獻1801條經驗 獲得超16個贊

一種簡單的變體是以I want to transition from X to Y while applying this function. 枚舉非常適合枚舉狀態機中所有可能/有效的狀態。我們需要一些東西來保持我們的狀態轉換——也許是Map<StateType, StateType>?但我們還需要某種State對象和修改它的方法 - 我們需要一個Map<StateType, Map<StateType, Transition>>. 請參閱下面的一些編譯示例代碼,可以幫助您入門。您可以按照自己喜歡的方式公開State對象(也許使其不可變?)并動態添加過渡。


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;

        }

    }

}

如果您的State對象類型依賴于當前的StateType.


查看完整回答
反對 回復 2023-06-21
?
慕工程0101907

TA貢獻1887條經驗 獲得超5個贊

如果您使用 Spring,您可以考慮 Spring Statemachine。?

我有一個我廣泛使用的個人設計,我稱之為“泵”。您的狀態機類有一個名為“pump”的函數,它會評估狀態并相應地更新。每個狀態評估可能需要來自外部源(控制器)的一些輸入,例如用戶或 AI。初始化狀態機時需要這些對象,并且通常是抽象實現。然后,您添加應用程序可以覆蓋以捕獲事件的事件回調。這種方法的一個優點是“泵”方法可以從單線程或多線程系統執行。


一旦你的機器建成,你就可以通過簡單地永遠調用泵并提供返回隨機值的控制器來輕松地進行單元測試。這實際上是一個“猴子”測試,以確保您的機器可以處理任何輸入組合而不會崩潰。


然后在你的應用程序中你只需要根據情況提供合適的控制器。


下面是一個非常粗略的狀態機,用于控制一個假設的骰子游戲。我省略了大部分細節,留下了方法的核心。請注意,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) {}

}


查看完整回答
反對 回復 2023-06-21
?
UYOU

TA貢獻1878條經驗 獲得超4個贊

我還建議您在實現自己的狀態機之前檢查兩個框架。狀態機理論對于自己開發來說真的很復雜,特別是沒有太多提及的概念,如子/嵌套狀態機是復雜/成功的狀態機設計所必需的。

一是上面提到的 Spring 狀態機,二是Akka 有限狀態機。

我的個人經驗 Spring State Machine 非常適合對諸如應用程序生命周期之類的事物進行建模,這些狀態包括 STARTING、INITIALISING、RUNNING、MAINTENANCE、ERROR、SHUTDOWN 等……但它對于建模諸如購物圖表之類的事物并不是很好、預訂、信用審批流程等...但它的內存占用太大,無法對數百萬個實例進行建模。

另一方面,Akka FSM 的占用空間確實很小,我個人實現了包含數百萬個狀態機實例的系統,并且它有另一個在 Spring 狀態機中完全缺失的工具。在現代 IT 中,一件事是不可避免的,變化,您建模的任何工作流程/流程都不會隨著時間的推移保持不變,因此您需要機制將這些變化集成到長期運行的工作流程/流程中(我的意思是,會發生什么如果您的流程在最新軟件版本之前啟動并保留舊模型,那么現在您有新版本并且模型已更改,您必須閱讀保留的流程并繼續使用新模型)。Akka 是針對此問題的內置解決方案Event / Schema Evolution。

查看完整回答
反對 回復 2023-06-21
  • 3 回答
  • 0 關注
  • 174 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號