State in Java

Why read if you can watch?

Watch State's video tutorial
read full article

State design pattern (distributed transition logic)

  1. Create a "wrapper" class that models the state machine
  2. The wrapper class contains an array of state concrete objects
  3. The wrapper class contains an index to its "current" state
  4. Client requests are delegated to the current state and "this" is passed
  5. Create a state base class that makes the concrete states interchangeable
  6. The State base class specifies default behavior for all messages
  7. The State derived classes only override the messages they need to
  8. The derived classes "call back to" the wrapper class to change its current
class FSM {                                                 // 1. The "wrapper"
private State[] states = { new A(), new B(), new C() }; // 2. States array
private int current = 0; // 3. Current state
public void on() { states[current].on( this ); } // 4. Delegation
public void off() { states[current].off( this ); } // and pass the
public void ack() { states[current].ack( this ); } // this pointer
public void changeState( int index ) { current = index; }
}

abstract class State { // 5. The State base class
public void on( FSM fsm ) { System.out.println( "error" ); } // 6. Default
public void off( FSM fsm ) { System.out.println( "error" ); } // behavior
public void ack( FSM fsm ) { System.out.println( "error" ); }
}

class A extends State {
public void on( FSM fsm ) { System.out.println( "A + on = C" );
fsm.changeState( 2 ); }
public void off( FSM fsm ) { System.out.println( "A + off = B" );
fsm.changeState( 1 ); }
public void ack( FSM fsm ) { System.out.println( "A + ack = A" );
fsm.changeState( 0 ); }
}

class B extends State {
public void on( FSM fsm ) { System.out.println( "B + on = A" );
fsm.changeState( 0 ); }
public void off( FSM fsm ) { System.out.println( "B + off = C" );
fsm.changeState( 2 ); }
}

class C extends State { // 7. Only override some messages
public void on( FSM fsm ) { System.out.println( "C + on = B" );
fsm.changeState( 1 ); } // 8. "call back to" the wrapper class
}

public class StateDemo2 {
public static void main( String[] args ) {
FSM fsm = new FSM();
int[] msgs = { 2, 1, 2, 1, 0, 2, 0, 0 };
for (int i=0; i < msgs.length; i++)
if (msgs[i] == 0) fsm.on();
else if (msgs[i] == 1) fsm.off();
else if (msgs[i] == 2) fsm.ack();
} }

A + ack = A A + off = B error B + off = C C + on = B error B + on = A A + on = C