Author image

Command Design Pattern


Difficulty:
1/5


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

Breakdown:
You are not encapsulating the object that sends the request, or the object that receives the request, but encapsulate the actual request as an object with state. Of course, some commands can be stateless chunks of pure behavior (no data members).
The command pattern also makes undoable/redoable operations a piece of cake (they're considerably harder to implement without it). Derived Commands can leverage CRTP to be statically bound.

Note that the code executing the commands is responsible for freeing their memory.

Design

  • define a base abstract class Command that represents a triggerable command for the program
  • create subclasses of Command, each representing a different concrete Command to be executed and override the interface method eg. void execute() (and optionally the undo operation void undo())
  • create a handler class CommandHandler which stores a pointer for each type of possible concrete Command subclass
  • use CommandHandler::executeCommand() to handle & dispatch the commands supplied by the incoming requests. You could use a switch with an enum such as CommandId to differentiate between the commands.
  • to support undo operations we store at the base command class the state that is being changed, ie all the state affected by the command and when undo() is requested we restore the oldstate. Likewise for redo().
  • to support multiple levels of undo instead of remembering the last command, we keep a stack<CommandType> commands; instead, and we point to the current one. When the user executes a command we push it to the stack. When the user undos we pop from the stack. When the user redos we first check if there is something to redo in the stack and proceed.


In my example I've used a slightly more complex version to create concrete Command classes. Instead of using the classic inheritance with virtual functions and making the base Command an interface (pure virtual) I resorted to the Curiously Recurring Template Pattern (aka Static Polymorphism) using templates. This is in general less flexible, more complicated but more performant. But more than that I wanted to illustrate a practical use for it. To familiarize yourself with CRTP check this tutorial.

I used Windows 8.1 x86_64, Visual Studio 2017 to build the project.

Github

Github repository link.


0 likes