State Design Pattern in Java: Case statement considered harmful

  1. Create a State class hierarchy
  2. The State base class has a single method void pull(Chain wrapper) The method can be abstract, or, it can contain default behavior
  3. Create a State derived class for each condition in the if-then-else statement
  4. Move each println() statement to the pull() method of its appropriate class
  5. Make the Chain class a "wrapper" class that models the state machine abstraction
  6. The Chain class maintains a "current" State object
  7. All client requests [i.e. pull()] are simply delegated to the current state object and the wrapper object's "this" pointer is passed
  8. The Chain class needs a constructor that initializes its current state
  9. It also needs a setState() method that the State derived classes can use to change the state of the state machine
  10. Call the setState() method as necessary in each of the State derived classes pull() methods
class Chain {
    private int state;

    public Chain() {
        state = 0;
    }

    public void pull() {
        if (state == 0) {
            state = 1;
            System.out.println( "   low speed" );
        } else if (state == 1) {
            state = 2;
            System.out.println( "   medium speed" );
        } else if (state == 2) {
            state = 3;
            System.out.println( "   high speed" );
        } else {
            state = 0;
            System.out.println( "   turning off" );
        }
    }
}

public class StateDemo {
    public static void main( String[] args ) throws IOException {
        InputStreamReader is = new InputStreamReader( System.in );
        Chain chain = new Chain();
        while (true) {
            System.out.print( "Press 'Enter'" );
            is.read();
            chain.pull();
        }
    }
}

Output

Press 'Enter'
   low speed
Press 'Enter'
   medium speed
Press 'Enter'
   high speed
Press 'Enter'
   turning off
Press 'Enter'
   low speed
Press 'Enter'
   medium speed
Press 'Enter'
   high speed
Press 'Enter'
   turning off

Code examples