5 min read

The State design pattern

State design pattern allows an object to alter its behavior when its internal state changes at runtime. Read more to learn about how to it works and a code example.
State Design Pattern
State Design Pattern

💡Intent

The State design pattern allows an object to alter its behavior when its internal state changes at runtime.

In the State pattern, an object's behavior is determined by its current state. The object can have one of a finite number of states, and it transitions from one state to another by executing methods defined for each state. These methods are called "state transitions."

🤔 The problem and use cases

Consider a simple light switch that can be in either the "on" or "off" state. The behavior of the light switch when the switch is flipped will depend on its current state. If the light switch is currently in the "off" state, flipping the switch will turn the light on. If the light switch is currently in the "on" state, flipping the switch will turn the light off.

Similarly consider a paint or Photoshop like software. That has a canvas object, where the behavior of the tool changes when the state changes from freehand drawing to creating objects, or adding/filling colors or erasing objects.

Other examples of problems where State design pattern is suitable:

  • ATM changing behavior as the state change from "welcome" to "login" to "transaction"
  • Online shopping carts changing behavior as the state changes from "empty" to "non-empty" to "order placed"
  • Network routers changing behavior as the state changes from "normal" to "congested" or "failure"

🌟The solution and example implementation

The State design pattern is proper when an object's behavior depends on its internal state, and when it is necessary to change the behavior of the thing at run-time based on that state.

Let's talk about the first example of light switch. The state design pattern can be used to implement the light switch in a way that makes it easy to add new states and state transitions.

We will create objects as following

State Design Pattern Class Diagram UML Diagram
Class Diagram of State Design Pattern

The light switch could be implemented as a Context class, with separate State classes for the "on" and "off" states. The Context class would maintain a reference to the current State object, and the State objects would define the behavior of the light switch when the switch is flipped.

This approach makes it easy to add new states to the light switch, such as a "dim" state or a "bright" state, without having to modify the Context class. It also makes it easy to understand and maintain the light switch, since the state transitions are clearly defined and separated from the rest of the object's behavior.

In this class diagram, the Context class maintains a reference to a State object, which represents the current state of the context. The Context class also has a setState() and getState() method for setting and getting the current state, and a handle() method that delegates the handling of the current state to the State object.

The State interface defines the interface for handling state transitions, and the ConcreteStateA and ConcreteStateB classes are concrete implementations of the State interface that represents different states of the context. Each of these classes has a handle() method that defines the behavior of the context when the handle() method is called on the Context object.

This allows the Context object to alter its behavior based on its current state, without the client code having to be aware of the specific details of the different states.

💻Code:

Here's an example in Java:


public interface State {
  void handle();
}

public class ConcreteStateA implements State {
  public void handle() {
    System.out.println("This is in State A");
  }
}

public class ConcreteStateB implements State {
  public void handle() {
    System.out.println("This is in State B");
  }
}

public class Context {
  private State state;

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

  public State getState() {
    return state;
  }

  public void handle() {
    state.handle();
  }
}

public class Main {
  public static void main(String[] args) {
    Context context = new Context();
    context.setState(new StateA());
    context.handle();  // Output: "This is in State A"
    context.setState(new StateB());
    context.handle(); // Output: "This is in State B"
  }
}

In this example, the Context class maintains a reference to a State object, which represents the current state of the context. The Context class also has a handle() method that delegates the handling of the current state to the State object.

The State interface defines the interface for handling state transitions. The ConcreteStateA and ConcreteStateB classes are concrete implementations of the State interface that represents different states of the context.

When the handle() method is called on the Context object, it delegates the call to the handle() method of the current State object. This allows the Context object to alter its behavior based on its current state, without the client code having to be aware of the specific details of the different states.

In general, the state design pattern is useful for any situation where the behavior of an object depends on its internal state and that behavior needs to be changed at run-time based on that state.

Pros and Cons

Pros ✅

  1. It allows an object to alter its behavior when its internal state changes, without the client code having to be aware of the specific details of the different states.
  2. It can reduce the complexity of an object by separating its behavior into distinct states, rather than having all of the behavior defined in a single class.
  3. It can make it easier to add new states to an object since the state transitions are handled by the state classes rather than the object itself.
  4. It can make it easier to maintain and debug an object since the state transitions are clearly defined and separated from the rest of the object's behavior.

Cons ❌

  1. It can make the code more complex since it requires the creation of multiple state classes and the implementation of state transitions.
  2. It can make the code more difficult to understand since the object's behavior is determined by its current state and the state transitions are not always obvious.
  3. It can make the object more difficult to test since its behavior depends on its current state and the state transitions.

Learning faster with Developer Diary

If you want to further improve your productivity, try out Developer Diary. Developer Diary brings clarity and insights to reach the Flow state faster. When you are working on your coding problem and remember to note something down or ask ChatGPT something, you can use a simple shortcut (`⌘+Shift+I`) to open the app and start journaling.

Learn Faster with this note taking app Developer Diary
Developer Diary by Invide

If you want to read more such article, do subscribe to our newsletter. Where we share the articles on technology, 100% remote developer jobs 🌎, developer productivity hacks, and insights from the Invide Remote Developers Community.

To discuss it with other fellow developers, join our Discord Server.