Your Guide to Design Patterns – State Pattern

Design Patterns State Pattern

This week we’ll continue our exploration of design patterns and look at a commonly used behavioural pattern, the State pattern.

The State Pattern

The Gang of Four book defines the State pattern as follows:

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

State Design Pattern

Think of a zone controller for a home irrigation system. It would have a number of states: disabled, enabled, idle, checking (for moisture level) and watering (the sprinklers are on). The ZoneController would move through a number of states as events get triggered in the system. Its behaviour is dependent on its current state. How would we actually implement those states in code?

State machines are usually implemented with lots of conditional statements (if..else or that select the appropriate behaviour depending on the current state of the object. Usually, this “state” is just a set of values of the object’s fields.

We can handle these different states inside the ZoneController by boolean flags representing each state. Handling the combinations of flags can become difficult when we are developing, modifying or maintaining the code. Any later use case or logic changes will cause changes to the conditional statements, often in many places in the code.

A better solution is to use the State design pattern. The state pattern defines a context class which is the ZoneController in this case. The context doesn’t implement the state logic internally, but rather delegates all the state-related work to a state object. We create new classes for each of the possible states of the context, and encapsulate the state-specific behaviours in these classes. We swap in an object of the correct state when the state changes.

The context stores a reference to a state object that represents its current state. As the states change, we replace the active state object with another object that represents the new state. All state classes implement the same interface so the context can use them interchangeably.

Requests that are state-dependent are forwarded to the current state object. Requests that are independent of state are handled directly in the context. Either the context or the concrete state objects are responsible for transitioning from one state to another.

Example Code

Back in our first person shooter game, we’ve decided that players should be able to buy Robot assistants that will help carry weapons and other supplies. A Robot will even be able to fight alongside the player if they’re not overloaded with supplies. This will be an upgrade option in a more advanced level of the game.

These Robot assistants will be battery powered, so they will have to be charged occasionally. Nuclear powered robots would be a nice option, but if their reactors are damaged they could explode, wreaking havoc on the game.

We can imagine that the Robot could be in a number of states: idle, charging, following, carrying, fighting, etc. We could model these states with a number of conditional statements (if..else or that select the appropriate behaviour depending on the current state of the Robot.

public class Robot {

   // fields for states
   private boolean isIdle;
   private boolean isCharging;
   private boolean isCarrying;
   private boolean isFighting;
   // methods with lots of clumsy conditional statements
} // end of class

As we’ve previously mentioned, this becomes very clumsy and difficult to modify and maintain.

Let’s rather model the states as a separate class.

public abstract class RobotState {
   // default behaviour for all methods is to signal an error.
   public void idle  (Robot robot) { error(); }
   public void charge(Robot robot) { error(); }
   public void carry (Robot robot) { error(); }
   public void fight (Robot robot) { error(); }

   private void error() {
      // some error signalling 
} // end of class

The Robot class now becomes simpler with no conditional code. All state logic is delegated to the state objects.

class Robot {

   // field for state
   private RobotState state;

   public Robot() {
      state = new IdleState();
    // methods with default behaviour
   public void idle() {
   public void charge() {
   public void carry() {
   public void fight() {

   // package visibility so only classes in the 
   // same package can trigger a state change.
   void changeState(RobotState state) {
      this.state = state;
} // end of class

The conditional statements to check whether the Robot can move from one state to another will be done in the specific concrete RobotState classes. The IdleState class follows:

public class IdleState extends RobotState {
   public void idle(Robot robot) {
      System.out.println("Already idling");
   public void charge(Robot robot) {
      System.out.println("Moving to charge state...");
      robot.changeState(new ChargeState());
   public void carry(Robot robot) {
      System.out.println("Moving to carry state...");
      robot.changeState(new CarryState());
   public void fight(Robot robot) {
      System.out.println("Moving to fight state...");
      robot.changeState(new FightState());
} // end of class

State Transitions

We need to think about which class should be responsible for state transitions. Should it be the context class (the Robot in this example) or the actual state objects (IdleStateChargeState, etc.)?

  • If the state transitions are independent of each other, then we would make the context responsible for state transitions.
  • If state transitions occur when events are received in other states, then we should put the state transition logic in the state objects themselves. The individual state objects (subclasses of RobotState) are responsible for state transitions.

The coupling between state objects is increased if they have the responsibility for the state transitions. The previous state must know about the next state. However, this usually results in code that is easier to understand and maintain.

State Pattern vs Strategy Pattern

The class structure of the State pattern and the Strategy pattern are identical. The key difference is intent; the patterns have different intents. The intent of the State pattern is to allow an object to change its behaviour when its internal state changes. The intent of the Strategy pattern is to encapsulate different algorithms and make them interchangeable.

Another difference between the two patterns is that a strategy is normally chosen once at instantiation time and is used for the duration of the application, while states are changed regularly during the running of an application. In the State pattern, the particular states are often aware of each other and they can initiate transitions from one state to another, while strategies almost never know about each other.

The State pattern implies a Strategy that changes frequently over time. Strategy sets an object’s behaviour at construction time.

Pros and Cons

Using the State pattern has a lot of benefits:

  • It follows the Single Responsibility principle. We model each individual state as a separate class with its own responsibility.
  • It conforms to the Open-Closed principle. We can create new state classes without changing any of the existing state classes or the context itself, as long as those classes all implement the same interface.
  • It simplifies the code of the context class by removing complicated state machine conditional statements.

However, using the pattern can be overkill if a state machine has only a few states or the states rarely change.

What’s next?

In the weeks ahead, we’ll continue examining some of the more useful design patterns. Stay tuned!

As always, please share your comments and questions.

Leave a Comment

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

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.