State in Java

Why read if you can watch?

Watch State's video tutorial
read full article

         State design pattern - an FSM with two states and one event
(distributed transition logic - logic in the derived state classes)
  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. The wrapper class contains a state transition table
  5. All client requests are simply delegated to the current state object
  6. Create a state base class that makes the concrete states interchangeable
  7. The State base class specifies default behavior for all messages
  8. The State derived classes only override the messages they need to
// 1. Create a "wrapper" class that models the state machine
class FSM {
private State[] states = { new A(), new B(), new C() }; // 2. states
private int[][] transition = { {2,1,0}, {0,2,1}, {1,2,2} }; // 4. transitions
private int current = 0; // 3. current
private void next( int msg ) { current = transition[current][msg]; }

// 5. All client requests are simply delegated to the current state object
public void on() { states[current].on(); next( 0 ); }
public void off() { states[current].off(); next( 1 ); }
public void ack() { states[current].ack(); next( 2 ); }
}

// 6. Create a state base class that makes the concrete states interchangeable
abstract class State {
public void on() { System.out.println( "error" ); } // 7. The State base
public void off() { System.out.println( "error" ); } // class specifies
public void ack() { System.out.println( "error" ); } // default behavior
}

class A extends State {
public void on() { System.out.println( "A + on = C" ); }
public void off() { System.out.println( "A + off = B" ); }
public void ack() { System.out.println( "A + ack = A" ); }
}

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

class C extends State {
// 8. The State derived classes only override the messages they need to
public void on() { System.out.println( "C + on = B" ); }
}

public class StateDemo {
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 on off ack A + off = B +---+---+---+ error A | C | B | A | B + off = C +---+---+---+ C + on = B B | A | C | | error +---+---+---+ B + on = A C | B | | | A + on = C +---+---+---+