Command Pattern

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 parameterize methods with different requests, delay or queue a request's execution, and support undoable operations.

Intent

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Motivation

Consider a user interface with buttons. Each button performs a specific action. Without the Command pattern, you would typically have each button directly call its associated action method. However, what if you need to:

The Command pattern provides a flexible solution by encapsulating each request as an object. This Command object contains all the necessary information to perform the action, including the receiver of the action and any parameters. This decouples the invoker (e.g., a button) from the receiver (the object that performs the action).

Command Pattern Structure

UML Diagram of Command Pattern

Note: This is a conceptual diagram. Actual implementation may vary.

Applicability

Use the Command pattern when you want to:

Structure

The Command pattern involves the following participants:

Consequences

Note: Implementing undo/redo requires commands to store enough information to reverse their actions. This might involve storing the old state of the receiver or parameters needed to revert the operation.

Example (Conceptual C#)

Let's imagine a simple application that can turn lights on and off.


// Receiver
public class Light
{
    public void TurnOn()
    {
        Console.WriteLine("Light is ON");
    }

    public void TurnOff()
    {
        Console.WriteLine("Light is OFF");
    }
}

// Command Interface
public interface ICommand
{
    void Execute();
    void Undo(); // For undoable operations
}

// Concrete Command for Turning On
public class LightOnCommand : ICommand
{
    private Light _light;

    public LightOnCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOn();
    }

    public void Undo()
    {
        _light.TurnOff(); // To undo turning on, turn it off
    }
}

// Concrete Command for Turning Off
public class LightOffCommand : ICommand
{
    private Light _light;

    public LightOffCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOff();
    }

    public void Undo()
    {
        _light.TurnOn(); // To undo turning off, turn it on
    }
}

// Invoker
public class Switch
{
    private ICommand _command;

    public void StoreCommand(ICommand command)
    {
        _command = command;
    }

    public void Press()
    {
        if (_command != null)
        {
            _command.Execute();
        }
    }

    public void PressUndo()
    {
        if (_command != null)
        {
            _command.Undo();
        }
    }
}

// Client
public class Program
{
    public static void Main(string[] args)
    {
        Light livingRoomLight = new Light();

        ICommand lightOn = new LightOnCommand(livingRoomLight);
        ICommand lightOff = new LightOffCommand(livingRoomLight);

        Switch remote = new Switch();

        // Turn on the light
        remote.StoreCommand(lightOn);
        remote.Press(); // Output: Light is ON

        // Turn off the light
        remote.StoreCommand(lightOff);
        remote.Press(); // Output: Light is OFF

        // Undo turning off
        remote.PressUndo(); // Output: Light is ON

        // Undo turning on
        remote.StoreCommand(lightOn); // Re-store the on command to undo it
        remote.PressUndo(); // Output: Light is OFF
    }
}
            
Tip: A MacroCommand can group multiple commands into a single command, allowing for complex actions to be executed as one.

Related Patterns