← All Patterns
behavioral4 participants

Command

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

The Problem

You need to support undo/redo, operation queuing, macro recording, or deferred execution. Calling methods directly gives you no way to reverse, store, or replay operations.

Structure

Clientcreatespush(cmd)Invokerexecute()«Command»ICommandexecute()undo()Receiveraction()history stack [ cmd3 | cmd2 | cmd1 ]push on execute

Execution Walkthrough

1

Create Command

Client creates a ConcreteCommand object, binding it to a Receiver (the object that actually does the work).

2

Pass to Invoker

3

execute()

4

Push to history

5

undo()

Code Comparison

Direct calls cannot be undone or queued. Every undo requires a parallel reverse-implementation scattered across the codebase.

// BAD: direct method calls — no undo, no history
class Editor {
  std::string doc_;
public:
  void insert(size_t pos, std::string text) {
    doc_.insert(pos, text);
    // How do we undo this? We'd need to track state manually
    // everywhere insert() is called.
  }
  void erase(size_t pos, size_t len) {
    doc_.erase(pos, len);
    // Same problem — no centralized reversal mechanism
  }
};

Full C++ Implementation

C++ · Command
#include <stack>
#include <memory>
#include <string>
#include <iostream>

struct Command {
  virtual void execute() = 0;
  virtual void undo()    = 0;
  virtual ~Command()     = default;
};

struct InsertCmd : Command {
  std::string& doc_;
  size_t       pos_;
  std::string  text_;

  InsertCmd(std::string& d, size_t p, std::string t)
    : doc_(d), pos_(p), text_(std::move(t)) {}

  void execute() override { doc_.insert(pos_, text_); }
  void undo()    override { doc_.erase(pos_, text_.size()); }
};

class CommandHistory {
  std::stack<std::unique_ptr<Command>> done_;
public:
  void execute(std::unique_ptr<Command> cmd) {
    cmd->execute();
    done_.push(std::move(cmd));
  }
  void undo() {
    if (done_.empty()) return;
    done_.top()->undo();
    done_.pop();
  }
  size_t size() const { return done_.size(); }
};

int main() {
  std::string doc;
  CommandHistory history;

  history.execute(std::make_unique<InsertCmd>(doc, 0, "Hello"));
  history.execute(std::make_unique<InsertCmd>(doc, 5, " World"));
  std::cout << doc << "\n";  // Hello World

  history.undo();
  std::cout << doc << "\n";  // Hello

  history.undo();
  std::cout << doc << "\n";  // (empty)
}

Participants

CommandConcreteCommandInvokerReceiver

Where it is used

Text editors

Every edit is a Command stored on a stack. Ctrl+Z pops and calls undo(); Ctrl+Y re-executes.

EDA tools

Schematic edits are Command objects. The tool replays or rolls back an entire design session.

Job schedulers

Tasks are Command objects enqueued for worker threads. Failed tasks call execute() again for retry.

Macro recording

IDE macros record each action as a Command sequence; playback calls execute() deterministically.

StrategyFactory Method