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..
}
skaffman
  • 398,947
  • 96
  • 818
  • 769
Sam Becker
  • 19,231
  • 14
  • 60
  • 80

2 Answers2

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.

Martin Andersson
  • 18,072
  • 9
  • 87
  • 115
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • 1
    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) – Asaf Nov 23 '11 at 10:52
  • 1
    This code enlightens your tough process especially in java. Thanks. – Trying Jul 03 '13 at 14:20
  • @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))`... – Tom Fink Jul 17 '13 at 12:34
  • 1
    Ok, figured it just out myself. Values of the enum obviously are not allowed inside constructors of the enum itself. :p – Tom Fink Jul 17 '13 at 16:21
  • @TomFink exactly. otherwise your version would of course be preferable – Sean Patrick Floyd Jul 17 '13 at 19:15
  • 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. – ceving Jun 12 '14 at 16:01
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

Allen
  • 1