Command Design Pattern
Command Deign Pattern is a behavioral design pattern that turns a request into standalone object.
Think of a Restaurant:
- The Customer (Client) decides what they want.
- The Waiter (Invoker) takes the order.
- The Order Slip (Command) is the object containing all the details.
- The Chef (Receiver) is the one who actually cooks the meal.
The Waiter doesn’t need to know how to cook; they just need to hand the “Command” (the slip) to the kitchen.
Problem without Command
Imagine this controller code:
if (action.equals("MOVE")) {
robot.move();
} else if (action.equals("STOP")) {
robot.stop();
} else if (action.equals("TURN_LEFT")) {
robot.turnLeft();
}Problems:
- Controller knows too much
- Tight coupling to
Robot - Adding a new action → modify controller
- No undo / queue / logging
- No way to treat actions as data
Requests are hard-coded, not first-class objects
Why Command pattern?
Command solves the problem of tight coupling between the code that requests an action and the code that performs it. By encapsulating a request as an object, it allows actions to be treated as first-class entities that can be stored, passed around, queued or undone. Follow open/closed Principle
Decouple sender from receiver.
Invoker does not know:
- Who executes the action
- How it is implemented
It only knows: command.execute();
When to use it?
Command should be used when actions must be executed at different times, logged for auditing, retried on failure or reversed. It is commonly used in UI frameworks, job schedulers, workflow engines, and transaction systems.
Example: Smart Home Remote
//The Command interface.
public interface Command {
void execute();
}
--------------------------------------------------------------------------------------------------------
/**
* The Receiver.
* Contains the actual business logic for a specific device.
*/
public class Light {
public void on() {
System.out.println("Light is ON");
}
public void off() {
System.out.println("Light is OFF");
}
}
--------------------------------------------------------------------------------------------------------
public class Stereo {
public void on() {
System.out.println("Stereo is ON");
}
public void off() {
System.out.println("Stereo is OFF");
}
}
--------------------------------------------------------------------------------------------------------
public class LightOnCommand implements Command {
// PRIVATE: Encapsulates the receiver so it's hidden from the outside
// FINAL: Ensures the command is linked to this specific light for its lifetime
private final Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
this.light.on();
}
}
--------------------------------------------------------------------------------------------------------
public class StereoOnCommand implements Command {
private final Stereo stereo;
public StereoOnCommand(Stereo stereo) {
this.stereo = stereo;
}
@Override
public void execute() {
this.stereo.on();
}
}
--------------------------------------------------------------------------------------------------------
/**
* The Invoker.
* Decoupled from the Receivers; it only knows about the Command interface.
*/
public class RemoteControl {
private Command slot;
public void setCommand(Command command) {
this.slot = command;
}
public void pressButton() {
if (slot != null) {
slot.execute();
}
}
}
--------------------------------------------------------------------------------------------------------
/**
* The Client (Main Method).
* Responsible for instantiating the objects and wiring them together.
*/
public class SmartHomeApp {
public static void main(String[] args) {
// 1. Initialize Receivers
Light livingRoomLight = new Light();
Stereo livingRoomStereo = new Stereo();
// 2. Initialize Commands (Passing receivers into constructors)
Command lightOn = new LightOnCommand(livingRoomLight);
Command stereoOn = new StereoOnCommand(livingRoomStereo);
// 3. Initialize Invoker
RemoteControl remote = new RemoteControl();
// 4. Client wires the Command to the Invoker
remote.setCommand(lightOn);
remote.pressButton(); // Output: Light is ON
remote.setCommand(stereoOn);
remote.pressButton(); // Output: Stereo is ON
}
}Command vs Strategy
A common point of confusion is how this differs from the Strategy Pattern. While both use an interface to encapsulate logic, their intent is different:
- Strategy is about how you do something (eg: Sort this list using QuickSort instead of MergeSort).
- Command is about what you want to do (eg: Turn on the Light). It treats the entire request as a ‘thing’ you can move, store or delay.
Strategy decides how something is done, while Command decides what action is executed and when.
Understanding the Boundary Using a Robot Example
1. Strategy Pattern — How the Robot Moves
The Strategy pattern is about how a task is performed.
In this case, it defines how the robot moves.
Get Aashna Chourasia’s stories in your inbox
Join Medium for free to get updates from this writer.
The robot can:
- Walk
- Fly
- Roll
Each is a movement algorithm, interchangeable at runtime as discussed in below article.
2. Command Pattern — What the Robot Should Do
The Command pattern answers a different question:
What action should the robot perform now?
Examples:
- Move
- Stop
- Turn left
- Pick an object
Command encapsulates a request as an object, separating:
- The invoker (controller)
- From the receiver (robot)
Command triggers the action, while Strategy determines how the action behaves.
// Command interface
interface Command {
void execute();
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Concrete commands
class MoveCommand implements Command {
private Robot robot;
public MoveCommand(Robot robot) {
this.robot = robot;
}
public void execute() {
robot.move();
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
class StopCommand implements Command {
private Robot robot;
public StopCommand(Robot robot) {
this.robot = robot;
}
public void execute() {
robot.stop();
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Invoker
class RobotController {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Receiver
class Robot {
private MoveStrategy moveStrategy;
public void setMoveStrategy(MoveStrategy moveStrategy) {
this.moveStrategy = moveStrategy;
}
public void move() {
moveStrategy.move();
}
public void stop() {
System.out.println("Robot stopped");
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Client
public class Main {
public static void main(String[] args) {
Robot robot = new Robot();
// Strategy decides HOW
robot.setMoveStrategy(new WalkStrategy());
// Command decides WHAT
Command moveCommand = new MoveCommand(robot);
RobotController controller = new RobotController();
controller.setCommand(moveCommand);
controller.pressButton(); // Output: Walking on two legs.
}
}






