#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, которую вы можете использовать напрямую: