From "Design Patterns"
🎧 Listen to Summary
Free 10-min PreviewCommand Pattern
Key Insight
The Command pattern encapsulates a request as an object, enabling clients to be parameterized with different requests, queuing or logging requests, and supporting undoable operations. This pattern is also known as Action or Transaction. Its motivation arises when requests need to be issued to objects without explicit knowledge of the operation or its receiver. For instance, user interface toolkits with elements like buttons and menus cannot embed specific application logic directly; instead, they use Command objects. The core concept involves an abstract `Command` class declaring an `Execute` operation. Concrete `Command` subclasses store a receiver object and implement `Execute` to invoke one or more corresponding operations on that receiver, which holds the necessary knowledge to fulfill the request. This design decouples the object invoking the operation (e.g., a menu item) from the object performing it (the receiver).
Practical applications include implementing menu choices: an `Application` configures `MenuItem` objects with `ConcreteCommand` instances. When a `MenuItem` is selected, it calls `Execute` on its command, which in turn acts on its receiver. Examples include a `PasteCommand` that invokes `Paste` on a `Document` receiver, or an `OpenCommand` that prompts for a document name, creates it, adds it to the `Application`, and opens it. A `MacroCommand` can execute a sequence of commands, allowing complex actions like 'center page and normal size' to be composed. This pattern provides significant flexibility in UI design, allowing features to be exposed via multiple interfaces (e.g., menu and push button sharing the same command instance) and supporting dynamic command replacement, context-sensitive menus, and command scripting. The Command pattern is applicable for parameterizing objects by actions, specifying/queuing/executing requests at different times, supporting undo/redo operations by storing state and an `Unexecute` method, enabling logging for crash recovery, and structuring systems around high-level operations built on primitives, especially in transactional contexts.
The pattern's participants include `Command` (abstract interface), `ConcreteCommand` (links receiver to action, implements `Execute`), `Client` (creates and configures `ConcreteCommand`), `Invoker` (requests command execution), and `Receiver` (knows how to perform the operations). Collaborations involve the client creating a `ConcreteCommand` and setting its receiver, the `Invoker` storing and later calling `Execute` on the command, and the `ConcreteCommand` then invoking operations on its receiver. For undoable commands, `ConcreteCommand` stores necessary state before execution. Implementation considerations include determining the 'intelligence' of a command, ranging from simple receiver-action bindings to self-contained logic or dynamic receiver discovery. Supporting multi-level undo/redo requires storing additional state (receiver, arguments, original values) and maintaining a history list of executed commands. To avoid error accumulation, `Memento` can be used to capture object states reliably. For simple, non-undoable commands without arguments, C++ templates can create `SimpleCommand` instances that bind a receiver object to a member function. `MacroCommand` manages and executes a sequence of subcommands, and if it supports undo, its subcommands must be unexecuted in reverse order. Commands whose state changes upon execution may need to be copied, acting as `Prototype`s, before being added to a history list.
📚 Continue Your Learning Journey — No Payment Required
Access the complete Design Patterns summary with audio narration, key takeaways, and actionable insights from Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides.