The Command Design Pattern: Turning Actions into Objects
Master the Command Pattern in Java. Learn how to encapsulate requests as objects to enable Undo/Redo, queuing, and macro commands.
Moshiour Rahman
The Problem: Hardcoded Buttons
Imagine you are building a Universal Remote Control. It has 4 buttons. If you code it like this:
class Remote {
private Light light;
private TV tv;
public void pressButton1() {
light.on(); // Hardcoded!
}
public void pressButton2() {
tv.volumeUp(); // Hardcoded!
}
}
This is rigid. You can’t change what Button 1 does at runtime. You can’t “record” a macro of clicks. You can’t “Undo”.
The Solution: The Command Pattern
The Command Pattern turns a request into a stand-alone object. This lets you parameterize methods with different requests, delay or queue a request’s execution, and support undoable operations.
Real-Life Analogy: Ordering at a Diner 🍔
- You (Client): Give an order (“Burger, no onions”) to…
- The Waiter (Invoker): Takes the order, writes it on a ticket (Command Object).
- The Cook (Receiver): Reads the ticket and cooks the burger.
The waiter doesn’t need to know how to cook a burger. They just hold the Command (Ticket) and pass it to the receiver.
Visualizing the Pattern

Implementation
1. The Command Interface
public interface Command {
void execute();
void undo(); // Critical for Undo features
}
2. The Receiver (The Hardware)
public class Light {
public void on() { System.out.println("Light ON"); }
public void off() { System.out.println("Light OFF"); }
}
3. Concrete Commands
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off(); // Simple undo logic
}
}
4. The Invoker (The Remote)
public class RemoteControl {
private Command slot;
public void setCommand(Command command) {
this.slot = command;
}
public void pressButton() {
slot.execute();
}
public void pressUndo() {
slot.undo();
}
}
Usage
RemoteControl remote = new RemoteControl();
Light livingRoomLight = new Light();
// Create the 'ticket'
Command lightOn = new LightOnCommand(livingRoomLight);
// Load the remote
remote.setCommand(lightOn);
// Press button
remote.pressButton(); // Output: Light ON
// Oops, didn't mean to
remote.pressUndo(); // Output: Light OFF
In The Wild (Real World Examples)
1. java.lang.Runnable
One of the interface definitions of Command is simply void execute(). Does that look familiar? Runnable is effectively a Command interface. Thread pools execute Runnables.
2. GUI Actions (Swing Action / JavaFX)
Text Editors use Command pattern heavily for Check/Undo operations on Ctrl+Z.
Cheat Sheet
| Feature | Details |
|---|---|
| Category | Behavioral |
| Problem Solved | Need for Undo/Redo, Job Queues, Macros |
| Key implementation | execute() method in an interface |
| Pros | Decoupling (Invoker doesn’t know Receiver), Undo/Redo support |
| Cons | Lots of tiny classes for every single action |
Tips to Remember 🧠
- “The Ticket”: Think of the diner order ticket. It’s an object representing an action.
- “Undo”: If you need Undo/Redo, you almost certainly need Command. You typically keep a
Stack<Command>history.
Moshiour Rahman
Software Architect & AI Engineer
Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.
Related Articles
The Visitor Design Pattern: Add Operations Without Modifying Classes
Master the Visitor Pattern in Java with practical examples. Add new operations to object structures without modifying existing classes using double dispatch.
JavaThe Observer Design Pattern: Don't Call Us, We'll Call You
Master the Observer Pattern in Java. Learn how to implement event-driven architectures and decouple data sources from listeners.
JavaThe Mediator Design Pattern: Centralize Complex Communications
Master the Mediator Pattern in Java. Learn how to reduce coupling by having objects communicate through a mediator instead of directly.
Comments
Comments are powered by GitHub Discussions.
Configure Giscus at giscus.app to enable comments.