Skip to content

Command Design Pattern (Behavioral)

Command 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.


Imagine you’re creating a new text-editor app. Your current task is to create a toolbar with a bunch of buttons for various operations of the editor. You created a very neat Button class that can be used for buttons on the toolbar, as well as for generic buttons in various dialogs.

While all of these buttons look similar, they’re all supposed to do different things. The simplest solution would be to create tons of subclasses for each place where the button is used. These subclasses would contain the code for executing a click.

Before long, you realize that this approach is deeply flawed. First, you have an enormous number of subclasses. Second, the Button class would depend on classes that it shouldn’t even know about, like the Editor class.

Good software design is often based on the principle of separation of concerns, which usually results in breaking an app into layers. The Command pattern suggests that GUI objects shouldn’t send these requests directly. Instead, you should extract all of the request details, such as the object being called, the name of the method and the list of arguments into a separate command class with a single method that triggers this request.

Command objects serve as links between various GUI and business logic objects. From now on, the GUI object doesn’t need to know what business logic object will receive the request and how it’ll be processed.

After a long walk in the city, you go to a nice restaurant and sit at the table. A waiter comes up to you and takes your order, writing it down on a piece of paper. The waiter goes to the kitchen and sticks the order on the wall. After a while, the order gets to the chef, who reads it and cooks the meal.

The paper order serves as a command. It remains in a queue until the chef is ready to serve it. The order contains all the relevant information required to cook the meal. It allows the chef to start cooking right away instead of running around trying to clarify the order details directly from you.


  1. Sender (Invoker) class is responsible for initiating requests. This class must have a field for storing a reference to a command object.
  2. Command interface usually declares just a single method for executing the command.
  3. Concrete Commands implement various kinds of requests. A concrete command isn’t supposed to perform the work on its own, but rather pass the call to one of the business logic objects.
  4. Receiver class contains some business logic. Almost any object may act as a receiver.
  5. Client creates and configures concrete command objects. The client must pass all of the request parameters, including a receiver instance, into the command’s constructor.
classDiagram
    class Invoker {
        -command: Command
        +setCommand(command: Command)
        +executeCommand()
    }
    class Command {
        <<interface>>
        +execute()
    }
    class ConcreteCommand {
        -receiver: Receiver
        -params
        +ConcreteCommand(receiver, params)
        +execute()
    }
    class Receiver {
        +operation(a, b, c)
    }

    Invoker o-- Command
    Command <|-- ConcreteCommand
    ConcreteCommand --> Receiver
    Client ..> ConcreteCommand
    Client ..> Invoker

# The base command class defines the basic interface for all
# concrete commands.
abstract class Command:
protected field app: Application
protected field editor: Editor
protected field backup: string
constructor Command(app, editor):
this.app = app
this.editor = editor
# Make a backup of the editor's state.
method saveBackup():
backup = editor.text
# Restore the editor's state.
method undo():
editor.text = backup
# The execution method is declared abstract to force all
# concrete commands to provide their own implementations.
abstract method execute()
# The concrete commands delegate the work to the receiver.
class CopyCommand extends Command:
method execute():
app.clipboard = editor.getSelection()
return false
class PasteCommand extends Command:
method execute():
saveBackup()
editor.replaceSelection(app.clipboard)
return true

  • Parameterize Objects with Operations: Use the Command pattern when you want to parameterize objects with operations.
  • Queue/Schedule Operations: Use the pattern when you want to queue operations, schedule their execution, or execute them remotely.
  • Reversible Operations: Use the pattern when you need to implement reversible operations (Undo/Redo).
  1. Declare the command interface with a single execution method.
  2. Extract requests into concrete command classes that implement the command interface.
  3. Identify classes that will act as invokers. Add fields for storing commands to these classes.
  4. Change the invokers so that they execute the command instead of sending a request to the receiver directly.
  5. The client must initialize objects in the following order: create receivers, create commands (associating them with receivers), create invokers (associating them with commands).

Pros:

  • Single Responsibility Principle: You can decouple classes that invoke operations from classes that perform these operations.
  • Open/Closed Principle: You can introduce new commands into the app without breaking existing client code.
  • You can implement undo/redo.
  • You can implement deferred execution of operations.
  • You can assemble a set of simple commands into a complex one.

Cons:

  • The code may become more complicated since you’re introducing a whole new layer between senders and receivers.
  • Chain of Responsibility, Command, Mediator, and Observer address various ways of connecting senders and receivers of requests.
  • Handlers in Chain of Responsibility can be implemented as Commands.
  • Command and Memento can be used together when implementing β€œundo”.
  • Command and Strategy may look similar because you can use both to parameterize an object with some action. However, they have very different intents.

// Command
public interface ICommand
{
void Execute();
}
// Receiver
public class Light
{
public void TurnOn() => Console.WriteLine("Light on");
public void TurnOff() => Console.WriteLine("Light off");
}
// Concrete Commands
public class TurnOnCommand : ICommand
{
private readonly Light _light;
public TurnOnCommand(Light light)
{
_light = light;
}
public void Execute() => _light.TurnOn();
}
public class TurnOffCommand : ICommand
{
private readonly Light _light;
public TurnOffCommand(Light light)
{
_light = light;
}
public void Execute() => _light.TurnOff();
}
// Invoker
public class RemoteControl
{
private ICommand _command;
public void SetCommand(ICommand command)
{
_command = command;
}
public void PressButton()
{
_command.Execute();
}
}
// Usage
class Program
{
static void Main()
{
var light = new Light();
var remote = new RemoteControl();
remote.SetCommand(new TurnOnCommand(light));
remote.PressButton();
remote.SetCommand(new TurnOffCommand(light));
remote.PressButton();
}
}