Command Pattern

Turn an action into an object, so it can be stored, queued, logged, undone and run by code that does not know what it does.

Overview

The Command pattern is one of the behavioral patterns in Design Patterns (Gamma, Helm, Johnson and Vlissides, 1994). A method call happens and is gone. A command is that call wrapped in an object: it holds the target, the arguments and an execute method. Because it is an object, it can be put in a list, sent across a queue, written to a log, run later, run again, or paired with an undo method that reverses it.

The pattern is behind undo and redo in every editor, behind job queues, and behind the way a toolbar button, a menu item and a keyboard shortcut all do the same thing. Interviewers ask about Command to see whether you can separate the thing that triggers an action from the thing that performs it, and whether you can build undo correctly, including the awkward cases: redo after a new action, and actions that must be grouped.

The problem it solves

A button needs to save the document. The simplest code puts document.save() in the button's click handler. Now the menu item needs the same, and the keyboard shortcut, and the auto-save timer. Each one calls the document directly, and the document must be reachable from all of them. Undo is impossible, because nothing remembers what was done.

  • The button knows the document and its methods — The button knows one thing: command.execute()
  • The same action is written in four places — One command object, bound to four triggers
  • No record of what ran — Commands can be kept in a history, a queue or a log
  • Undo needs special code everywhere — Each command knows how to undo itself

Structure

  • Command interface — execute(), and undo() when reversal is needed — Command
  • Concrete command — Holds the receiver and the arguments; knows how to do and undo one action — Insert, Delete
  • Receiver — Does the real work — Document
  • Invoker — Triggers commands and may keep them — History, a button, a queue worker
  • Client — Builds commands and hands them to the invoker — the editor's setup code

How undo and redo work

Two stacks do all the work. Running a command pushes it on the undo stack and clears the redo stack. Undo pops the undo stack, calls undo(), and pushes the command on the redo stack. Redo pops the redo stack, calls execute() again, and pushes it back on the undo stack.

Where you already use it

  • Java Swing UndoManager — an UndoableEdit — Keeps an ordered list of edits and an index; adding an edit after an undo drops the edits after the index; the default limit is 100 edits
  • Java ExecutorService.submit(Runnable) — a Runnable — The task is an object handed to a pool that runs it later and returns a Future
  • A job queue (any language) — a serialized job record — A worker takes a job and calls one method on it without knowing what the job does

What you will be able to do

  • Draw the five participants and say which of them knows which.
  • Build undo and redo with two stacks and get the redo-after-new-action case right.
  • Decide, per command, whether to store the state needed for undo or to compute the inverse.
  • Group commands into a macro whose undo runs in reverse.
  • Explain how a command becomes a queued job or a log entry, and what that requires.

Interview questions

  • How do you implement undo and redo, and what are the tricky cases?
  • What is a macro command, and how does it relate to Composite?
  • How does Command turn into a job queue?
  • How is Command different from Strategy? Both wrap behavior in an object.
  • Why should the invoker not know the receiver? Show the coupling and the fix.

Sign up free to read the full topic

More Low-Level Design topics

Start free on Cariara · Coding problems · System design studio