Command Pattern in C#

The Command Pattern turns a request into a standalone object that can be stored, queued, or executed later. This gives you full control over how and when actions are performed, while keeping senders and receivers decoupled.

Real-Life Analogy: Voice Assistant (e.g. Alexa, Siri)

When you ask a voice assistant to “turn on the lights” or “play music”, it doesn’t immediately know how to do that. It turns your voice command into a request and sends it to the correct device or service.

The assistant doesn’t need to know how lights or speakers work — it just triggers the appropriate command. That’s the idea behind the Command Pattern: separating the request from its execution.

Voice assistant sending commands to smart devices
Like a voice assistant forwarding your commands to the right device, the Command Pattern encapsulates requests as objects so they can be queued, logged, or executed flexibly.

Benefits of Command Pattern

The Command Pattern is ideal when you want to add undo, scheduling, or logging behaviour around actions. It promotes loose coupling by turning actions into objects and isolating the caller from the receiver.

This is especially helpful when the exact operation isn’t known in advance, or you want to queue or repeat actions.

  • Encapsulates behaviour as an object
  • Enables undo/redo and logging
  • Decouples the sender of a command from its executor

When Should You Use It?

Use the Command Pattern when you want to issue requests without knowing what will handle them. It works well when you want to queue tasks, record history, or structure complex UI interactions.

It suits cases where:

  • Requests must be handled later, queued, or scheduled
  • You need undo/redo functionality
  • UI elements (like buttons or menus) need reusable actions

When Not to Use It: Avoid it when requests are simple and unlikely to need scheduling or history — extra layers may be unnecessary.

What to Implement

To implement this pattern, you need:

A command interface, concrete command classes for each action, a receiver that performs the real work, and an invoker that calls the command.

  • Command Interface: Declares the Execute() method
  • Concrete Commands: Implement specific actions
  • Receiver: The object that actually performs the task
  • Invoker: Stores and calls commands

How It Works in C#


// Receiver
public class SmartDevice
{
    public void TurnOn() => Console.WriteLine("Device is now ON");
    public void TurnOff() => Console.WriteLine("Device is now OFF");
}

// Command Interface
public interface ICommand
{
    void Execute();
}

// Concrete Commands
public class TurnOnCommand : ICommand
{
    private readonly SmartDevice _device;
    public TurnOnCommand(SmartDevice device) => _device = device;
    public void Execute() => _device.TurnOn();
}

public class TurnOffCommand : ICommand
{
    private readonly SmartDevice _device;
    public TurnOffCommand(SmartDevice device) => _device = device;
    public void Execute() => _device.TurnOff();
}

// Invoker
public class VoiceAssistant
{
    private ICommand _command;

    public void SetCommand(ICommand command) => _command = command;
    public void ProcessCommand() => _command.Execute();
}

Usage:


var device = new SmartDevice();
var turnOn = new TurnOnCommand(device);
var turnOff = new TurnOffCommand(device);

var assistant = new VoiceAssistant();

assistant.SetCommand(turnOn);
assistant.ProcessCommand();  // Device is now ON

assistant.SetCommand(turnOff);
assistant.ProcessCommand();  // Device is now OFF

Final Thoughts

The Command Pattern makes it easy to structure actions that might need to be repeated, queued, or reversed — just like a voice assistant does with your smart devices.

It gives you the flexibility to decouple input from action and makes your system more modular, testable, and extendable.

Command Pattern in C# | SimplyAdvanced.dev