Introduction

Imagine you are building a smart home application.

The application controls various devices:

  • Lights

  • Fans

  • Air Conditioners

  • Television

  • Speakers

A beginner might write something like: class RemoteControl {


Initially, this works.

But what happens when new devices are added?

  • Garage Door

  • Curtains

  • Security Camera

  • Smart Lock

The remote control class keeps growing.

Soon, it becomes difficult to:

  • Add new commands

  • Maintain existing code

  • Support undo operations

  • Schedule tasks

  • Store command history

This is where the Command Design Pattern helps.

Instead of directly executing actions, we convert each request into an object.

What is the Command Pattern?

The Command Pattern is a behavioral design pattern that encapsulates a request as an object.

In simple words:

The Command Pattern converts an action into an object.

Instead of directly calling methods, the client creates command objects that represent actions.

These command objects can then be:

  • Executed

  • Stored

  • Queued

  • Logged

  • Undone

  • Replayed

Real World Analogy

Think about ordering food in a restaurant.

There are four participants:

Customer:

"I want a Burger."

Waiter:

Takes the order.

Chef:

Prepares the food.

Kitchen Equipment:

Actually cooks the food.

The waiter doesn't cook.

The customer doesn't enter the kitchen.

The order slip acts like a Command object.

It contains the request and can be passed around without either side knowing implementation details.

Why Do We Need the Command Pattern?

Suppose we are building a smart home remote.

Without the Command Pattern:


This creates several problems.

Problems Without Command Pattern

1. Large Conditional Statements

As devices increase:

if(...)
else if(...)
else if(...)

The code becomes difficult to maintain.

2. Tight Coupling

The remote directly knows every device.

Remote → Light
Remote → Fan
Remote → TV

Adding new devices requires modifying the remote.

3. No Undo Support

Actions execute immediately.

Undo functionality becomes difficult.

4. No Command History

Executed actions cannot be stored easily.

Solution: Command Pattern

The Command Pattern introduces a new layer.

Instead of directly performing actions, we do:

Remote → Command → Device

Now the remote only knows about commands.

Commands know how to interact with devices.

Key Components of Command Pattern

The Command Pattern typically consists of:

1. Command Interface

Defines a common execute operation.

2. Concrete Commands

Actual command implementations.

3. Receiver

The object that performs the real work.

4. Invoker

Triggers command execution.

5. Client

Creates and connects everything.

Structure of Command Pattern

Client
   │
   ▼
Command
   ▲
   │
Concrete Command
   │
   ▼
Receiver

Invoker
   │
   ▼
Command

Example: Smart Home Remote

Let's implement a simple smart home system.

Step 1: Create Receiver

The receiver performs actual work.


Step 2: Create Command Interface


Step 3: Create Concrete Commands

Light ON Command:


Light OFF Command:


Step 4: Create Invoker


Step 5: Client Code


Output

Light is ON

Light is OFF

How the Command Pattern Works

Let's understand the complete flow.

Step 1

The client creates a receiver.

Light light;

Step 2

The client creates commands.

LightOnCommand
LightOffCommand

Step 3

The invoker receives commands.

remote.setCommand(...)

Step 4

The invoker executes commands.

command->execute();

Step 5

The command delegates work to the receiver.

light->turnOn();

Key Idea Behind Command Pattern

The most important idea is:

Encapsulate a request as an object.

Once requests become objects, they can be:

  • Stored

  • Queued

  • Logged

  • Scheduled

  • Replayed

  • Undone

This flexibility is the biggest strength of the pattern.

Implementing Undo Functionality

One of the most famous applications of the Command Pattern is Undo/Redo.

Modify the interface:


Light ON Command:


Now every command knows how to reverse itself.

Command History

Commands can be stored:


Whenever a command executes:


Undo:


This is how many editors implement Undo functionality.

Macro Commands

A Command can also contain multiple commands.

Example:

Movie Mode

Actions:

Turn Off Lights
Turn On TV
Turn On Speakers
Close Curtains

Instead of pressing multiple buttons, one command executes all actions.

Example:


This is called a Macro Command.

Command vs Strategy Pattern

A common interview question.

Command PatternStrategy Pattern
Encapsulates requestsEncapsulates algorithms
Focuses on actionsFocuses on behavior
Supports undo/redoSupports runtime algorithm switching
Commands can be queuedStrategies are usually executed immediately
Represents an operationRepresents an approach

Command vs Observer Pattern

CommandObserver
Executes actionsSends notifications
Action-orientedEvent-oriented
Usually one receiverMultiple observers
Explicit executionAutomatic notification

Advantages of Command Pattern

1. Loose Coupling

The invoker does not know the receiver's details.

2. Easy Extensibility

New commands can be added without modifying existing code.

3. Supports Undo/Redo

One of the biggest benefits.

4. Command History

Commands can be stored and replayed.

5. Task Scheduling

Commands can execute later.

6. Macro Operations

Multiple commands can be grouped.

Disadvantages of Command Pattern

1. Increased Number of Classes

Every action usually requires a command class.

2. Additional Complexity

For very simple systems, the pattern may feel excessive.

3. More Objects

Applications may create many command instances.

Real World Applications

The Command Pattern is heavily used in:

  • Text editors (Undo/Redo)

  • IDEs

  • Smart home systems

  • Menu systems

  • Task schedulers

  • Job queues

  • Database transaction systems

  • GUI frameworks

  • Macro recording software

  • Remote control systems

Many desktop applications rely heavily on Command Pattern concepts.

Common Beginner Mistakes

1. Putting Business Logic in Invoker

The invoker should only execute commands.

Avoid:

if(...)

inside the invoker.

2. Creating Commands Without Receivers

Commands should delegate actual work to receivers.

3. Ignoring Undo Requirements

If undo functionality is needed later, design commands accordingly.

4. Creating Too Many Tiny Commands

Not every small operation requires a separate command.

Use the pattern when operations represent meaningful actions.

Simple Visualization

Without Command:

Remote
   │
   ├── Light
   ├── Fan
   ├── TV
   └── AC

The remote directly depends on devices.

With Command:

Remote
   │
   ▼
Command
   │
   ▼
Receiver

The command acts as a bridge between the invoker and the receiver.

Summary

The Command Design Pattern encapsulates requests as objects, allowing operations to be executed, stored, queued, logged, and undone independently of the objects that perform the actual work.

By decoupling the sender from the receiver, the pattern makes systems more flexible, extensible, and maintainable. It is especially useful when applications require features such as undo/redo, command history, task scheduling, or macro operations.

Whenever actions need to be treated as first-class objects, the Command Pattern provides a clean and scalable solution.