State Pattern in C#

The State Pattern allows an object to change its behaviour when its internal state changes. It removes large conditional blocks and puts each behaviour into a separate class based on the current state.

Real-Life Analogy: Phone Modes — Silent, Vibrate, Normal

Think of your phone. When it's in Silent mode, incoming calls don't make noise. In Vibrate mode, it buzzes. In Normal mode, it rings. The phone is the same, but its response depends on its current mode.

That's the essence of the State Pattern: an object behaves differently depending on its internal state, but its interface stays the same.

Phone switching between Silent, Vibrate, and Normal modes
Like a phone responding differently in each mode, the State Pattern allows the same object to change behaviour based on its internal state.

Benefits of State Pattern

This pattern helps eliminate complex switch-case or if-else chains by moving state-specific logic into separate classes. Each state class handles only one situation, making the system easier to understand and extend.

When the object's state changes, it simply switches to another class that knows what to do.

  • Keeps logic for each state separate and clear
  • Makes code easier to test and modify
  • Supports adding new states without touching existing logic

When Should You Use It?

Use the State Pattern when an object must behave differently depending on its internal condition, and those behaviours should be cleanly separated.

It's ideal when:

  • Objects go through well-defined state changes
  • Behaviour needs to be updated without cluttering code
  • You want to avoid large conditional statements

When Not to Use It: Avoid it for objects with very few simple states that rarely change — the extra structure may not be worth it.

What to Implement

To apply this pattern, you need:

A state interface, one class for each state, and a context class that holds the current state and delegates behaviour to it.

  • State Interface: Declares what the object can do
  • Concrete States: Implement behaviour for specific modes
  • Context: Stores current state and forwards calls

How It Works in C#


// State Interface
public interface IPhoneMode
{
    void HandleIncomingCall(Phone phone);
}

// Concrete States
public class SilentMode : IPhoneMode
{
    public void HandleIncomingCall(Phone phone)
    {
        Console.WriteLine("Incoming call... (No sound)");
        phone.SetState(new VibrateMode());
    }
}

public class VibrateMode : IPhoneMode
{
    public void HandleIncomingCall(Phone phone)
    {
        Console.WriteLine("Incoming call... (Vibrating)");
        phone.SetState(new NormalMode());
    }
}

public class NormalMode : IPhoneMode
{
    public void HandleIncomingCall(Phone phone)
    {
        Console.WriteLine("Incoming call... (Ringing)");
        phone.SetState(new SilentMode());
    }
}

// Context
public class Phone
{
    private IPhoneMode _mode;

    public Phone(IPhoneMode initialMode)
    {
        _mode = initialMode;
    }

    public void SetState(IPhoneMode mode)
    {
        _mode = mode;
    }

    public void IncomingCall()
    {
        _mode.HandleIncomingCall(this);
    }
}

Usage:


var phone = new Phone(new SilentMode());

phone.IncomingCall(); // No sound
phone.IncomingCall(); // Vibrating
phone.IncomingCall(); // Ringing

Final Thoughts

The State Pattern allows objects to switch behaviour dynamically without changing their interface. Like a phone changing how it reacts to calls based on its mode, your objects can respond differently without messy conditionals.

It brings clarity and flexibility to state-dependent behaviour — making your code easier to extend and maintain.