All Courses
OOP: DESIGN PATTERNS

Command Pattern

Concept Definition

Command turns a request into an object. Instead of calling an action immediately, you store an object that knows how to execute that action later. The caller can queue, log, retry, or undo commands using one common interface.

Think of a remote control button. The button does not know the details of a fan or light; it only triggers the command assigned to it.

Why It Matters

Many programs need to treat actions uniformly. A menu item, toolbar button, keyboard shortcut, task queue, or transaction log may all need the same operation: execute(). Command separates the object that asks for work from the object that performs the work.

Command is also a bridge from basic polymorphism to real application design. It applies OOP to verbs, not only nouns.

Syntax Block

class Command {
public:
    virtual ~Command() = default; // safe base cleanup
    virtual void execute() = 0;   // action contract
};

Explained Code

Example: Toolbar Commands

#include <iostream> // std::cout
#include <memory>   // std::unique_ptr
#include <vector>   // std::vector

class Command {
public:
    virtual ~Command() = default;                 // safe polymorphic deletion
    virtual void execute() = 0;                   // common action
};

class SaveCommand : public Command {
public:
    void execute() override { std::cout << "Saved\n"; } // perform save action
};

class Toolbar {
private:
    std::vector<std::unique_ptr<Command>> commands; // owns command objects

public:
    void add(std::unique_ptr<Command> command) {     // receive action object
        commands.push_back(std::move(command));      // store for later
    }

    void runAll() {
        for (auto& command : commands) { command->execute(); } // execute uniformly
    }
};

Toolbar does not know what each button does. It only stores commands and calls execute().

Key Points / Rules

  • Use Command when actions need to be stored, delayed, queued, logged, or undone.
  • The invoker calls the command; the receiver performs the real work.
  • A command object can hold the data needed to perform the action.
  • Use std::unique_ptr<Command> when a container owns commands polymorphically.
  • Add undo() only when the command can truly reverse its effect.

Common Mistakes

  1. Making commands too large. A command should represent one clear action.
  2. Letting the invoker know concrete command types. That reintroduces coupling.
  3. Claiming undo is easy for every command. Some actions, such as sending an email, cannot be perfectly undone.
  4. Using Command for direct one-line calls. If nothing is stored or delayed, a function call may be simpler.

Quick Check

  1. What method does every command class implement?
  2. Why can Toolbar run different commands through the same loop?

Viva Answer

Command represents an action as an object. It is useful for queues, button actions, logging, retry systems, and undo/redo designs.