ConceptDifficulty: Intermediate3 min

Command Pattern: Turning a Request Into an Object

Once a request is an object, it can wait in a queue, be logged, or be undone.

The Command pattern wraps a request in an object with one method to carry it out, usually called execute. The code that triggers the request holds that object instead of calling the code that does the work, so the request can be stored, queued, logged, sent elsewhere, or reversed. This card covers the problem that calls for it, the intent, and when it fits.

The problem is a trigger tied to the code it runs. A toolbar button in a text editor calls editor.bold() directly. The button cannot be reused for another action, the call leaves no record, and once it has happened there is nothing to undo, because the request never existed as anything but a call.

A button that calls, and a button that holds a command

Without the patternthe button knows the editor

py
class BoldButton:
    def click(self):
        self.editor.bold()

One button class per action, and the call is gone once it has run.

With the patternthe button knows a command

py
class Button:
    def __init__(self, command):
        self.command = command

    def click(self):
        self.command.execute()
        history.append(self.command)

One button class for every action, and each press leaves an object in the history.

The Gang of Four state the intent as: encapsulate a request as an object, thereby letting you parameterise clients with different requests, queue or log requests, and support undoable operations.

An order ticket in a restaurant is a familiar picture. The waiter writes the order once, it waits on a rail until a cook is free, and it says exactly what to make without the waiter knowing how. The picture breaks on reversal: a meal cannot be uncooked, while a command that remembers what it changed can undo itself.

Command is one of eleven behavioural patterns, the family concerned with which object does which part of the work, and how objects communicate.

The behavioural family, with this pattern marked
PatternWhat it does
Chain of ResponsibilityPasses a request along a chain of handlers until one handles it.
Command (this topic)Turns a request into an object that can be stored, queued or undone.
InterpreterRepresents a small language's grammar as classes and evaluates its sentences.
IteratorVisits the elements of a collection without exposing how it is stored.
MediatorRoutes the communication between objects through one central object.
MementoCaptures an object's state so it can be restored later.
ObserverNotifies many objects when one object changes.
StateChanges an object's behaviour when its internal state changes.
StrategySwaps one algorithm for another behind a common interface.
Template MethodFixes an algorithm's steps in a base class and lets subclasses fill some in.
VisitorAdds operations to a class hierarchy without changing its classes.
Command

Use it when

  • An action must be undone, redone, or replayed.
  • Requests must wait in a queue, run on another thread, or run at a scheduled time.
  • The thing that triggers an action, such as a button or a menu item, should not know what the action does.

Avoid it when

  • The action runs once, at once, and is never stored, so a direct call is clearer.
  • Every command would be a class around a single call with no undo and no queue.
  • The state an undo needs is the whole document, which is a snapshot's job rather than a command's.