Type Behavioral
Purpose Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

Description

The State pattern enables the context to behave differently depending on the state that it's in. This is achieved by representing each state as a separate class that implements a common State interface.

Implementing the State pattern can ensure that:

  • Large monolithic conditional statements can be avoided.
  • State transitions can be made more explicit and easier to understand.
  • New states can often be added easily with minimal changes to existing code.

Overview

State
Context Maintains a reference to the current State object and delegates state-dependent behaviour to it.
State Defines the interface used by the Context to delegate state-dependent behaviour.
ConcreteState Implements the State interface and provides behaviour associated with a particular state of the Context.

Implementation

// State

public interface ITrafficLightState
{
    void Change(TrafficLight light);
}

// Concrete States

public class GreenLightState : ITrafficLightState
{
    public void Change(TrafficLight light)
    {
        Console.WriteLine("Green light - Go!");
        light.State = new YellowLightState();
    }
}

public class YellowLightState : ITrafficLightState
{
    public void Change(TrafficLight light)
    {
        Console.WriteLine("Yellow light - Be careful!");
        light.State = new RedLightState();
    }
}

public class RedLightState : ITrafficLightState
{
    public void Change(TrafficLight light)
    {
        Console.WriteLine("Red light - Stop!");
        light.State = new GreenLightState();
    }
}

// Context

public class TrafficLight(ITrafficLightState initialState)
{
    public ITrafficLightState State { get; set; } = initialState;

    // handler
    
    public void Change() => State.Change(this);
}

// Demonstration

public static class StateDemo
{
    public static void Execute()
    {
        var light = new TrafficLight(new RedLightState());
        
        for (var i = 0; i < 5; i++)
        {
            // request 
            
            light.Change();
        }
    }
}

Summary

For more information, please see here.