State Design Pattern in C#: Real-World Example and Use Cases


In any software application, there will be many different features or modules that need to work together.

Some of them will be simple.

Some of them will be a bit more complex.

And perhaps you need to change the state for one of the classes. If that’s the case with your application, then you can use the State design pattern.

The State pattern is a behavioral design pattern that allows an object to change its behavior based on its internal state. The pattern is used to create objects that represent various states and transitions between those states.

This article will explain what the state design pattern is and show you a real-world example of using the State design pattern in C#. At the end of the article, I will show you a secret sauce that will make the State pattern shine in your application.

What is the State design pattern in C#?

state pattern

The state of an object is its current condition. It includes both its physical state such as:

  •  position,
  • velocity,
  • orientation,

As well as its internal state, such as:

  • temperature,
  • pressure,
  • charge.

An object can be in a set of states, and a state transition is a process of changing from one state to another.

A common example of a state object is a light switch.

It has two states: on and off. An event, such as pressing the button, causes the switch to move from one state to another. By doing so, the light goes on or off.

Another example is a car.

It has several states, such as parkeddriving, and stopped. Each state represents what the car is currently doing, such as not moving or currently moving. Transitions can be caused by events, such as the car stalling when driving or turning the car ignition on.

When it comes to programming, there are multiple ways to implement an object’s state and transition. You can write a lot of conditional statements, or you can use the State design pattern.

You can use the State pattern to specify what happens to the object when its internal state changes. After the change, the object will change its state class, which controls how it should behave.

The state pattern can be used to handle conditional behavior, perform different actions based on the state of an object, and model finite state machines. A finite state machine (FSM) is a computation model used in mathematics that defines that a machine can be in one of a finite number of states. The machine can change from one state to another in response to some external or internal event. Changing from one state to another is known as a transition.

The State design pattern is a behavioral design pattern.

These patterns can be defined as the patterns that deal with communication and interaction between objects.

The behavioral patterns are:

When to use the State design pattern?

Use the State pattern in the following situations:

  • You have an object that needs to have different behavior depending on its current state. Use it when the number of states is enormous, and your code frequently changes depending on the state.
  • You can use the State pattern when you have a class filled with many conditions that control or alter how the class behaves according to the current values of the class fields. How you refactor to the State pattern is that you extract conditional branches into separate state classes. By doing that, you can separate the state-specific code from the main class.
  • You can also use the State pattern if you have a lot of transitions between different classes’ states.

How to implement the State pattern in C#

The original implementation, defined in the Design Patterns book, talks about the following participants of the State design pattern:

  • Context – defines an interface for clients to interact. It maintains references to concrete state objects, which you may use to define their current state.
  • State – defines an interface for declaring what each concrete state should do.
  • Concrete State – provides an implementation for the methods defined in the state.

The following image represents a UML diagram of the C# State design pattern.

 Let’s see some code for implementing the State pattern in C#.

State pattern – Real-world example in C#

Let’s take a look at an example of a Computer. You are probably reading this article on your computer (or your phone, but that’s also a computer, in a way). A computer has different states like ON, OFF, and SLEEP. When its state changes, the behavior of computers also changes.

Let’s look at the implementation of this simple example:

public class Computer
{
    private State _currentState;

    public Computer()
    {
        _currentState = new OffState();
    }

    public void PressPowerButton()
    {
        _currentState.PressPowerButton(this);
    }

    public void SetState(State state)
    {
        _currentState = state;
    }
}

public interface State
{
    void PressPowerButton(Computer computer);
}

public class OnState : State
{
    public void PressPowerButton(Computer computer)
    {
        Console.WriteLine("Computer is already on. Going to sleep mode...");
        computer.SetState(new SleepState());
    }
}

public class OffState : State
{
    public void PressPowerButton(Computer computer)
    {
        Console.WriteLine("Turning on computer...");
        computer.SetState(new OnState());
    }
}

public class SleepState : State
{
    public void PressPowerButton(Computer computer)
    {
        Console.WriteLine("Waking up computer from sleep mode...");
        computer.SetState(new OnState());
    }
}

And the usage:

Computer computer = new Computer();

// Initial state is Off
computer.PressPowerButton(); // Output: "Turning on computer..."

// State is now On
computer.PressPowerButton(); // Output: "Computer is already on. Going to sleep mode..."

// State is now Sleep
computer.PressPowerButton(); // Output: "Waking up computer from sleep mode..."

You can see in the above code example that the Computer class has a state, and the PressPowerButton changes the computer’s state.

If you are in the OFF state and press the power button, the computer will TURN ON. If the computer is in the ON state, then pressing the button will put it in the SLEEP state.

Benefits of using the State pattern

The State design pattern has the following benefits:

  • It localizes state-specific behavior and partitions behavior for different states
  • It makes state transitions explicit
  • State objects can be shared

What are related patterns to the State design pattern?

The related patterns to the State pattern are the Flyweight and Singleton design patterns. The Flyweight defines how and when to share the State objects. On the other hand, you can sometimes define State objects as singletons.

Conclusion

The State Design Pattern allows you to alter an object’s behavior when its internal state changes.

Using the State design pattern would be much easier to track all the possible conditions or the states, and this will ensure that our application will have less undefined behavior.

To design an effective State pattern, you must list all possible states and relate each state with each other or define a sequence of states to be changed.

If you want to learn more about design patterns, check the separate in-depth article about design patterns in C#.

Recent Posts