DEV Community

Cover image for Design Patterns Simplified: Part 9 – Command Pattern (a.k.a. “Your Code’s Remote Control”)
Prateek Prabhakar
Prateek Prabhakar

Posted on • Edited on • Originally published at Medium

Design Patterns Simplified: Part 9 – Command Pattern (a.k.a. “Your Code’s Remote Control”)

Command Pattern belongs to the Behavioral category of design patterns.

Why? Because it is all about decoupling WHAT needs to be done, from WHO does it and WHEN it is done.
It encapsulates a request (or an action) as a standalone object, giving you the flexibility to,

  • Trigger actions on demand (just like pressing a remote button)
  • Queue them up for later
  • Log or audit what was executed, and
  • Even undo the action if needed!

It is like handing your code a remote control, where each button is a command waiting to be executed.

Let's take an example of a TV Remote

Imagine you are using a TV remote sitting comfortably on your couch to binge watch the most awaited new season of your favorite web series.
You press the "Power" button, and the TV turns on.
You press the "App" button, and you are navigated to the particular app.
You press "Volume Up", and the sound increases.

All set, right? Just need popcorns now (Wish we had a remote for the popcorn too! Anyways, not until we have robots doing these stuff for us).
You don’t even care how the remote talks to the TV internally, right?
Each button press just represents a command, and the remote knows how to execute it.

In coding terms, this is exactly what the Command Pattern does. It decouples the sender (remote) from the receiver (TV) and encapsulates each request (power, volume) as a command object.


What is the Command Pattern?

It is a design pattern that turns a request or action into a separate object, so that, you can pass it around, queue it, log it, or even undo it later.
In short, it separates the action’s intent from its execution.

Home Automation System

Let’s say you are building a GUI for a Home Automation System.
There is a UI button for turning on lights.
Your code looks something like this,

Class LightService
    Method TurnOn()
        Print("Light turned ON")

// Button click event binding
button.OnClick = LightService.TurnOn

// When button is clicked
button.OnClick()
Enter fullscreen mode Exit fullscreen mode

Seems simple, but what if,

  • You want to add undo/redo?
  • Queue commands for batch execution?
  • Log what actions were triggered?

This tight coupling would definitely not scale.
Here comes, Command Pattern to the rescue.

What does the code look like?

// Step 1: Command Interface
Interface ICommand
    Method Execute()
    Method Undo();

// Step 2: Concrete Command
Class TurnOnLightCommand Implements ICommand
    Constructor(lightService)
        this.lightService = lightService

    Method Execute()
        lightService.TurnOn()

    Method Undo()
        lightService.TurnOff()

// Step 3: Receiver (actual business logic)
Class LightService
    Property isOn = false

    Method TurnOn()
        isOn = true
        Print("Light is ON")

    Method TurnOff()
        isOn = false
        Print("Light is OFF")

// Step 4: Invoker (the caller, e.g., a button)
Class Button
    Constructor(command, history)
        this.command = command
        this.history = history

    Method Click()
        command.Execute()
        history.Push(command)

// Step 5: Command History (for Undo functionality)
Class CommandHistory
    Property stack = empty stack

    Method Push(command)
        stack.Push(command)
        Log(command)

    Method Undo()
        If stack is not empty
            command = stack.Pop()
            command.Undo()
            Print("Undo performed")
        Else
            Print("No commands to undo")

    Method Log(command)
        Print("Command Executed: " + command.TypeName())

// Step 6: Caller logic
lightService = new LightService()
history = new CommandHistory()

turnOnCommand = new TurnOnLightCommand(lightService)
turnOffCommand = new TurnOffLightCommand(lightService)

onButton = new Button(turnOnCommand, history)
offButton = new Button(turnOffCommand, history)

onButton.Click()    // Output: Light is ON
offButton.Click()   // Output: Light is OFF

history.Undo()      // Output: Undo performed (Light is ON)
history.Undo()      // Output: Undo performed (Light is OFF)
history.Undo()      // Output: No commands to undo
Enter fullscreen mode Exit fullscreen mode

What Did We Achieve?

In this code, we achieved the Command Pattern by encapsulating action (turning the light ON) into separate command objects that implement an interface, which can later be extended to other actions.
The Button (invoker) triggers these commands without knowing their internal details, while the LightService (receiver) executes the actual operations. This decoupling allows us to easily add features like undo and command logging through the command history, making the system flexible, reusable, and easy to extend.
Hence, in totality,

  • Sender and receiver are decoupled
  • Can add Undo, Redo, or Queue behavior easily
  • Reusable commands can be plugged into different invokers

When Should You Use the Command Pattern?

Use the Command Pattern when you need to decouple the action from the invoker, especially in scenarios like,

  • GUI-based systems: Menus, toolbars, and buttons triggering different commands
  • Undo/Redo functionality: In editors, form actions, or transactional systems
  • Task scheduling: Queuing commands for later or repeated execution
  • Logging and auditing: Keeping a history of actions executed
  • Game controls or IoT actions: Wrapping inputs like “Move”, “Attack”, or remote device operations

In short, any time you need to treat an action as a first class object — to execute, queue, undo, or log, the Command Pattern fits perfectly.


To summarize, it would be apt to say,

The Command Pattern lets you wrap actions as objects, so you can easily run them later, undo them, or keep a history, all while keeping your code clean and flexible.

Hope this article made the Command Pattern easier to grasp, and that you will feel confident using it in your next project.

Next Up in the Series: Chain of Responsibility Pattern. Do give it a read...

Top comments (0)