Lesson 11 of 17 2 min

LLD Lesson: The Command Pattern

Learn how to encapsulate actions as objects to support Undo/Redo, queuing, and decoupled execution.

1. The Problem: Tight Coupling of Senders and Receivers

Imagine a Remote Control that can turn on a Light, open a Garage, or play a Radio.

  • If the Remote class has hardcoded logic for light.turnOn(), garage.open(), etc., it becomes massive and hard to maintain.

2. The Solution: Command Pattern

We wrap the action into a Command object. The Remote just knows it needs to call command.execute().

Step 1: The Command Interface

public interface Command {
    void execute();
    void undo();
}

Step 2: Concrete Commands

public class LightOnCommand implements Command {
    private Light light;
    public void execute() { light.on(); }
    public void undo() { light.off(); }
}

Step 3: The Invoker (Remote)

public class RemoteControl {
    private Command slot;
    public void setCommand(Command c) { this.slot = c; }
    public void pressButton() { slot.execute(); }
}

3. Real-world Intuition: The Restaurant Order

You (The Client) tell the Waiter (The Invoker) what you want. The Waiter writes it on a piece of paper (The Command). The Chef (The Receiver) cooks the food. The Waiter doesn't need to know how to cook; they just pass the "Command" paper to the kitchen.

4. Why use it?

  • Undo/Redo: Keep a stack of executed commands. To undo, just call pop().undo().
  • Macro Commands: Combine multiple commands into one (e.g., "Party Mode" turns on lights, plays music, and dims blinds).
  • Queuing: Commands can be stored in a queue and processed by workers later.

Final Takeaway

Use the Command pattern whenever you need to parameterize objects with actions or support reversible operations.

Want to track your progress?

Sign in to save your progress, track completed lessons, and pick up where you left off.