Как создать простой конечный автомат в java

#java #state-machine

#java #конечный автомат

Вопрос:

В настоящее время я изучаю Java и хотел бы знать, как управлять состоянием OO-способом. Я реализовал приложение Pong. Если бы я хотел иметь несколько состояний, таких как игровой процесс и меню, и каждое из этих состояний должно было выполнять start, stop и run, как бы я этого добился и как бы я переключался между этими состояниями.

Я знаю, что мог бы просто добавить большой оператор switch, но каков наилучший способ реализовать это?

Я хочу иметь возможность переключаться в состояние меню в состоянии игрового процесса и наоборот.

 import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class Pong extends Applet implements Runnable, KeyListener{

    public void start ()
    {
        setSize(screen);
        setFocusable(true);
        Thread th = new Thread (this);
        th.start ();
    }

    public void stop()
    {
    }
    //Etc..
}
  

Ответ №1:

Вы можете смоделировать базовый FSM (конечный автомат), используя перечисления:

 public enum State {

    ONE {
        @Override
        public Set<State> possibleFollowUps() {
            return EnumSet.of(TWO, THREE);
        }
    },

    TWO {
        @Override
        public Set<State> possibleFollowUps() {
            return EnumSet.of(THREE);
        }
    },

    THREE // final state 

    ;
    public Set<State> possibleFollowUps() {
        return EnumSet.noneOf(State.class);
    }

}
  

Хотя код для генерации этого будет очень подробным, если все усложнится, приятной частью является то, что вы получаете безопасность во время компиляции, потокобезопасность и высокую производительность.

Комментарии:

1. ПРИМЕЧАНИЕ: при переопределении методов в определенных перечислениях их класс отличается. (в этом случае THREE.getClass() — это состояние, а TWO.getClass() может быть состоянием $ 2)

2. Этот код упрощает ваш сложный процесс, особенно на java. Спасибо.

3. @Sean: Принимая во внимание комментарий Асафа, я хотел бы знать, видите ли вы какой-либо недостаток в передаче возможных последующих состояний в конструкторе в разные состояния вместо перезаписанных методов? (например ONE(EnumSet.of(TWO, THREE)), TWO(EnumSet.of(THREE))

4. Хорошо, разобрался сам. Очевидно, что значения перечисления не разрешены внутри конструкторов самого перечисления. :p

5. @TomFink точно. в противном случае ваша версия, конечно, была бы предпочтительнее

Ответ №2:

Вам не обязательно делать это самостоятельно, вот очень простая, но мощная реализация конечного автомата на основе Java8, которую вы можете использовать напрямую:

https://github.com/swiftech/SWState