State Design Pattern


Intent

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

Also known as

Objects for States

Explanation

Real world examples

1. Suppose we want to implement a TV Remote with a simple button to perform action. If the State is ON, it will turn on the TV and if state is OFF, it will turn off the TV.

2. Consider a class TCPConnection that represents a network connection.A TCPConnection object can be in one of several different states:Established, Listening, Closed.

Wikipedia says

The state pattern is a behavioral software design pattern that implements a state machine in an object-oriented way. With the state pattern, a state machine is implemented by implementing each individual state as a derived class of the state pattern interface, and implementing state transitions by invoking methods defined by the pattern's super class.

Structure


Participants

1. Context
  • defines the interface of interest to clients.
  • maintains an instance of a ConcreteState subclass that defines the current state.
2. State
  • defines an interface for encapsulating the behavior associated with a particular state of the Context.
3. ConcreteState subclasses
  • each subclass implements a behavior associated with a state of the Context.

Collaborations

  • Context delegates state-specific requests to the current ConcreteStateobject.
  • A context may pass itself as an argument to the State object handling the request. This lets the State object accessthe context if necessary.
  • Context is the primary interface for clients. Clients can configure a context with State objects. Once a context is configured, its clients don't have to deal with the State objects directly.
  •  Either Context or the ConcreteState subclasses can decide which statesucceeds another and under what circumstances.

Implementation (state start and stop example)

Let's create a State interface defining an action and concrete state classes implementing the State interface. Context is a class which carries a State.
StatePatternDemo, our demo class, will use Context and state objects to demonstrate change in Context behavior based on type of state it is in.
Step 1 : Create an interface.

State.java
public interface State {
   public void doAction(Context context);
}
Step 2 : Create concrete classes implementing the same interface.
StartState.java
public class StartState implements State {

   public void doAction(Context context) {
      System.out.println("Player is in start state");
      context.setState(this); 
   }

   public String toString(){
      return "Start State";
   }
}
 StopState.java
public class StopState implements State {

   public void doAction(Context context) {
      System.out.println("Player is in stop state");
      context.setState(this); 
   }

   public String toString(){
      return "Stop State";
   }
}
Step 3 : Create Context Class.
Context.java
public class Context {
   private State state;

   public Context(){
      state = null;
   }

   public void setState(State state){
      this.state = state;  
   }

   public State getState(){
      return state;
   }
}
Step 4 : Use the Context to see change in behaviour when State changes.
StatePatternDemo.java
public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();

      StartState startState = new StartState();
      startState.doAction(context);

      System.out.println(context.getState().toString());

      StopState stopState = new StopState();
      stopState.doAction(context);

      System.out.println(context.getState().toString());
   }
}
Step 5 : Output
Player is in start state
Start State
Player is in stop state
Stop State

Implementation (TV Remote example)

We will use State pattern to implement TV Remote example.
Step 1 : Create an interface.
public interface State {
 public void doAction();
}
Step 2: State Design Pattern Concrete State Implementations
In our example, we can have two states – one for turning TV on and another to turn it off. So we will create two concrete state implementations for these behaviors.

public class TVStartState implements State {
 @Override
 public void doAction() {
  System.out.println("TV is turned ON");
 }
}
public class TVStopState implements State {
 @Override
 public void doAction() {
  System.out.println("TV is turned OFF");
 }
}
Step 3 : Let's implement our Context object that will change its behavior based on its internal state.
public class TVContext implements State {

 private State tvState;

 public void setState(State state) {
  this.tvState=state;
 }

 public State getState() {
  return this.tvState;
 }

 @Override
 public void doAction() {
  this.tvState.doAction();
 }

}
Notice that Context also implements State and keep a reference of its current state and forwards the request to the state implementation.
Step 4 :  Now let’s write a simple program to test our state pattern implementation of TV Remote.
public class TVRemote {

 public static void main(String[] args) {
  TVContext context = new TVContext();
  State tvStartState = new TVStartState();
  State tvStopState = new TVStopState();
  
  context.setState(tvStartState);
  context.doAction();
  
     context.setState(tvStopState);
  context.doAction(); 
 }
}
Step 5 : Output
TV is turned ON
TV is turned OFF

View source code on my github repository :

Applicability

Use the State pattern in either of the following cases
  • an object's behavior depends on its state, and it must change its behavior at run-time depending on that state
  • operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects.

Real world examples