State Design Pattern in Java

Introduction

State pattern comes under behavior design pattern in JEE. The State design pattern allows an object to alter its behavior when its internal state changes. State pattern is used to provide a systematic and lose-coupled way to achieve this through Context and State implementations. Context is the class that has a state reference to one of the concrete implementations of the state and forwards the request to the state object for processing. This can be a cleaner way for an object to change its behavior at runtime without resorting to large monolithic conditional statements such as using switch-case or if-else statements.

The original definition of State Pattern in Gang of Four Book is given below

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

When should we use State Pattern?

You should use the State pattern when the behavior of an object should be influenced by its internal state.

Example

A TV can be switched ON or OFF. So TV is either in ON or OFF state. A person can be in HAPPY or in EMOTIONAL state.

Implementation

Let’s look at an example of the state pattern. First, you need to define the State interface. It declares one method, doAction().

The StartState class is a Concrete State that implements doAction() of State. This displays a message when a car is started.

package com.roytuts.designpattern.strategy;
public interface State {
  void doAction();
}

The StartState class is a Concrete State that implements doAction() of State. This displays a message when a car is started.

package com.roytuts.designpattern.state;
public class StartState implements State {
  @Override
  public void doAction() {
    System.out.println("Start the Engine of the Car");
  }
}

The MovingState class is a Concrete State that implements doAction() of State. This displays a message when a car is moving after started.

package com.roytuts.designpattern.state;
public class MovingState implements State {
  @Override
  public void doAction() {
    System.out.println("Move the Car");
  }
}

The StopState class is a Concrete State that implements doAction() of State. This displays a message when a car is stopped after started.

package com.roytuts.designpattern.state;
public class StopState implements State {
  @Override
  public void doAction() {
    System.out.println("Stop the Engine of the Car");
  }
}

The Car class is the Context class. It contains an State reference to a concrete state. In this example, you have a Car that implements the State reference, and you pass the calls to Car’s doAction() method on to the corresponding method on the state reference. As a result of this, a Car object behaves differently depending on the state of Car (i.e., the current State reference, the car can be in different states such as start, moving, stop).

package com.roytuts.designpattern.state;
public class Car implements State {
  private State state;
  public Car(State state) {
    this.state = state;
  }
  public State getState() {
    return state;
  }
  @Override
  public void doAction() {
    state.doAction();
  }
}

The StatePatternTest class demonstrates the state pattern. First, it creates a Car object with a StartState object. It displays the results of doAction() when the car object is in the start state. Next, the car object’s state is changed with a MovingState object. It displays the result of doAction(), and you see that in the moving state, the car object’s behavior is different. Again you change the car object’s state to a StopState and display the result of doAction().

package com.roytuts.designpattern.state;
public class StatePatternTest {
  /**
   * @param args
   */
  public static void main(String[] args) {
    Car car = new Car(new StartState());
    car.doAction();
    car.setState(new MovingState());
    car.doAction();
    car.setState(new StopState());
    car.doAction();
  }
}

The console output as shown below

Start the Engine of the Car
Move the Car
Stop the Engine of the Car

Benefits of State Pattern

The benefits of using State pattern to implement polymorphic behavior is clearly visible, the chances of error are less and it is very easy to add more states for additional behavior making it more robust, easily maintainable and flexible. Also State pattern helps in avoiding if-else or switch-case conditional logic in this scenario.

That’s all. Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *