How to create a simple state machine in java
Asked Answered
S

2

15

I am currently learning java and would like to know how to control state in a OO way. I implemented a Pong app. If I wanted multiple states like gameplay and menu, and each one of these states had to execute start, stop and run how would I achieve this and how would I switch between these states.

I know I could simply throw in a big switch statement but what's the best way to implement this?

I want to be able to switch to the menu state in the gameplay state and vice versa.

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..
}
Saleratus answered 26/4, 2011 at 12:28 Comment(0)
P
32

You can simulate a basic FSM (Finite State Machine) using enums:

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);
    }

}

While the code to generate this will be very verbose if things get more complicated, the nice part is that you get compile-time safety, thread-safety and high performance.

Piffle answered 26/4, 2011 at 12:44 Comment(6)
NOTE: when overriding methods in specific enums, their class is not the same. (in this case THREE.getClass() is State, and TWO.getClass() could be State$2)Procurable
This code enlightens your tough process especially in java. Thanks.Mckim
@Sean: Noting Asaf's comment, I would like to know, if you would see any disadvantage passing the possible follow up states in a constructor to the different states instead of the overwritten methods? (like ONE(EnumSet.of(TWO, THREE)), TWO(EnumSet.of(THREE))...Shana
Ok, figured it just out myself. Values of the enum obviously are not allowed inside constructors of the enum itself. :pShana
@TomFink exactly. otherwise your version would of course be preferablePiffle
Why do you say this is compile-time safe? If you provide a method possibleFollowUps it is obvious that decision if a transition is valid takes place at run time and not at compile time. You will get compile time safety only be modeling every state as an object with a method for each transition.Choiseul
A
0

You don't have to do it yourself, here is a very simple but powerful state machine implementation based on Java8 that you can utilize directly:

https://github.com/swiftech/SWState

Abomb answered 17/7, 2022 at 5:2 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.