Skip to content

Command Pattern: Encapsulating Requests

Command Pattern: Encapsulating Requests

The Command Pattern is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation lets you pass requests as a method arguments, delay or queue a requestโ€™s execution, and support undoable operations.

๐Ÿ—๏ธ The Problem

Imagine you are building a Smart Home Remote Control. Each button on the remote should perform an action (e.g., Turn on Light, Close Garage Door). If you hardcode the logic for each button, adding new buttons becomes a nightmare. Also, you want to support Undo and Redo.

๐Ÿš€ The .NET Implementation

In .NET, the Command pattern is powerful for building complex UIs, transactional systems, or task queues.

1. The Command Interface

public interface ICommand
{
    void Execute();
    void Undo();
}

2. The Receiver (The object that performs the work)

public class Light
{
    public void On() => Console.WriteLine("Light is ON");
    public void Off() => Console.WriteLine("Light is OFF");
}

3. Concrete Commands

public class LightOnCommand : ICommand
{
    private readonly Light _light;

    public LightOnCommand(Light light) => _light = light;

    public void Execute() => _light.On();
    public void Undo() => _light.Off();
}

4. The Invoker (The Remote Control)

public class RemoteControl
{
    private ICommand _lastCommand;

    public void PressButton(ICommand command)
    {
        _lastCommand = command;
        _lastCommand.Execute();
    }

    public void PressUndo()
    {
        _lastCommand?.Undo();
    }
}

๐Ÿ› ๏ธ Real-World Usage (Client)

var livingRoomLight = new Light();
var lightOn = new LightOnCommand(livingRoomLight);

var remote = new RemoteControl();

// 1. Execute the command
remote.PressButton(lightOn);

// 2. Undo the last action
remote.PressUndo();

๐Ÿ’ก Why use Command?

  • Undo/Redo Support: Easy to implement since the action is encapsulated in an object.
  • Queueing: You can store commands in a list (e.g., Queue<ICommand>) and execute them later.
  • Decoupling: The remote control doesnโ€™t need to know anything about the light or how to turn it on.