State Pattern

State pattern is a behavioral design pattern which allows a class behavior to changes based on its state.

This pattern closely resembles with Strategy Pattern. It is used to encapsulate varying behavior for the same object based on its internal state.

The intent of this pattern, according to Design Patterns by Gamma et al, is to

  • Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

The proper use of state pattern can be a cleaner way for an object to change its behavior at runtime without resorting to large monolithic conditional statements and thus improve maintainability.

 

Structure

In state pattern, objects are created which represent various states and a context object whose behavior varies as its state object changes.

The following diagram shows the structure of state pattern.

state pattern structure

Figure: State Pattern Structure

Here,

  • Context class is a single interface to the outside world.
  • a State class is an abstract base class for all concrete states.
  • ConcreteStateA, ConcreteStateB, ConcreteStateC, … represent the different "states" of the state machine as derived classes of the State base class. State-specific behaviors are defined in the appropriate State derived classes.
  • Maintain a pointer to the current "state" in the "context" class. To change the state of the state machine, change the current "state" pointer.

 

Example

Let us consider a case in which we have to write the software that goes into a fancy ceiling fan. This ceiling fan has 3 speeds, with 2 pull chain cords. A red pull chain cord and a green pull chain cord.

The ceiling fan always starts in the Off state.

The behavior can be depicted in the state diagram as below:

state pattern example problem

Figure: Ceiling Fan behavior

The State pattern can improve our application when we have different behavior in different states.

With state pattern, we can create different states that themselves are responsible for creating and setting the next state. This means that the business rule deciding the next state, is implemented in the states themselves. This also means that the Application class only knows about the start state. This promotes good object oriented design principles like program to interface, decoupling etc.

 

The implementation class diagram for above application is as below:

state pattern example

Figure: State pattern example : Ceiling fan

Here, The CeilingFan class is independent of the states (including the start state). So, if we add a new state, then we don’t need to modify the CeilingFan class.

 

Java Implementation

Let us first create FanState interface that represents State.

/**
 * State
 */
public interface FanState {
    void printState();
    FanState nextState();
    FanState previousState();
}

Now, the following are the concrete classes that represents different states for objects.

/**
 * concrete state
 */
public class Off implements FanState {
    @Override
    public void printState() {
         System.out.println(" fan is off ");
    }

    @Override
    public FanState nextState() {
        return new LowSpeed();
    }

    @Override
    public FanState previousState() {
        return new HighSpeed();
    }
}
public class LowSpeed implements FanState {
    @Override
    public void printState() {
        System.out.println(" low speed ");
    }

    @Override
    public FanState nextState() {
        return new MediumSpeed();
    }

    @Override
    public FanState previousState() {
        return new Off();
    }

}
public class MediumSpeed implements FanState {
    @Override
    public void printState() {
        System.out.println(" medium speed ");
    }

    @Override
    public FanState nextState() {
        return new HighSpeed();
    }

    @Override
    public FanState previousState() {
        return new LowSpeed();
    }
}
public class HighSpeed implements FanState {
    @Override
    public FanState nextState() {
        return new Off();
    }

    @Override
    public FanState previousState() {
        return new MediumSpeed();
    }

    @Override
    public void printState(){
        System.out.println(" high speed ");
    }
}

Now, a CeilingFan class is created that represent context.

/**
 * context
 */
public class CeilingFan {
    private FanState currentState;

    public CeilingFan() {
        currentState = new Off();
    }

    public void pullGreen() {
        setCurrentState(currentState.nextState());
        currentState.printState();

    }

    public void pullRed() {
        setCurrentState(currentState.previousState());
        currentState.printState();
    }

    public void setCurrentState(FanState currentState) {
        this.currentState = currentState;
    }
}

We are all set with our application. The following code snippet represents the client for our application.

/**
 * Client
 */
public class Application {
    public static void main(String[] args) {
        CeilingFan fan = new CeilingFan();
        fan.pullGreen();
        fan.pullGreen();
        fan.pullGreen();
        fan.pullGreen();
        fan.pullRed();
        fan.pullRed();
    }
}

The output of the program is:

low speed 
 medium speed 
 high speed 
 fan is off 
 high speed 
 medium speed

The output shows that we are able to have different behavior when we have different states in application.

Iterator Pattern
Chain of Responsibility Pattern