Menu
Coddy logo textTech

Command Pattern

Part of the Object Oriented Programming section of Coddy's Java journey — lesson 70 of 87.

The Command Pattern is a behavioral design pattern that turns a request into a stand-alone object containing all information about the request. This transformation lets you pass requests as method arguments, delay or queue a request's execution, and support undoable operations.

Think of it like a restaurant: instead of telling the chef directly what to cook, you write your order on a slip. The waiter (invoker) takes the slip (command) to the kitchen, where it can be queued, prioritized, or even cancelled. The pattern decouples the object that invokes the operation from the one that performs it.

The pattern has four key components: a Command interface declaring the execute method, ConcreteCommand classes that implement specific actions, a Receiver that performs the actual work, and an Invoker that triggers commands:

interface Command {
    void execute();
}
class Light {  // Receiver
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}
class RemoteControl {  // Invoker
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

The invoker doesn't know what action will be performed—it just calls execute():

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Output: Light is ON

The Command Pattern excels when you need to queue operations, implement undo/redo functionality, or schedule tasks for later execution. Each command encapsulates everything needed to perform an action, making your system more flexible and extensible.

challenge icon

Challenge

Easy

Let's build a smart home automation system using the Command Pattern! You'll create a system where various home devices can be controlled through commands, allowing actions to be queued, executed, and even stored for later use—just like a universal remote control that doesn't need to know how each device works internally.

You'll organize your code across four files:

  • Command.java: Define the Command interface that all device commands will implement. It should declare a single method execute() that performs the command's action.
  • Devices.java: Create two receiver classes that represent smart home devices:

    Television - has methods powerOn() that prints TV is now ON, powerOff() that prints TV is now OFF, and setChannel(int channel) that prints TV channel set to [channel].

    Thermostat - has methods setTemperature(int temp) that prints Thermostat set to [temp] degrees and turnOff() that prints Thermostat turned OFF.

  • Commands.java: Create concrete command classes that encapsulate device operations:

    TVOnCommand - takes a Television in its constructor and calls powerOn() when executed.

    TVOffCommand - takes a Television in its constructor and calls powerOff() when executed.

    TVChannelCommand - takes a Television and an int channel in its constructor, and calls setChannel() with that channel when executed.

    ThermostatSetCommand - takes a Thermostat and an int temperature in its constructor, and calls setTemperature() with that value when executed.

  • Main.java: Create a RemoteControl class (the invoker) that has a method setCommand(Command cmd) to store a command and pressButton() to execute the stored command.

    In your main method, you'll receive two inputs: a TV channel number (integer) and a thermostat temperature (integer).

    Create a Television and a Thermostat. Create a RemoteControl and demonstrate the Command Pattern by:

    1. Setting a TVOnCommand and pressing the button
    2. Setting a TVChannelCommand with your input channel and pressing the button
    3. Setting a ThermostatSetCommand with your input temperature and pressing the button
    4. Setting a TVOffCommand and pressing the button

You will receive two inputs in order: the TV channel (integer) and the thermostat temperature (integer).

For example, with inputs 5 and 72, your output would be:

TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFF

Notice how the RemoteControl never directly interacts with the devices—it only knows about the Command interface. Each command encapsulates everything needed to perform its action, making it easy to add new devices and commands without changing the invoker!

Cheat sheet

The Command Pattern is a behavioral design pattern that encapsulates a request as an object, allowing you to parameterize clients with different requests, queue or log requests, and support undoable operations.

The pattern decouples the object that invokes the operation (invoker) from the one that performs it (receiver).

Key Components

  • Command: Interface declaring the execute() method
  • ConcreteCommand: Classes implementing specific actions
  • Receiver: Object that performs the actual work
  • Invoker: Object that triggers commands

Basic Structure

// Command interface
interface Command {
    void execute();
}

// Receiver
class Light {
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}

// ConcreteCommand
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}

// Invoker
class RemoteControl {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

Usage

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Output: Light is ON

The invoker doesn't know what action will be performed—it just calls execute(). This makes the system flexible and extensible, ideal for queuing operations, implementing undo/redo functionality, or scheduling tasks.

Try it yourself

import java.util.Scanner;

// TODO: Create RemoteControl class (the invoker) with:
// - setCommand(Command cmd) method to store a command
// - pressButton() method to execute the stored command

class RemoteControl {
    // TODO: Implement RemoteControl
}

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Read inputs
        int channel = scanner.nextInt();
        int temperature = scanner.nextInt();
        
        // TODO: Create a Television and a Thermostat
        
        // TODO: Create a RemoteControl
        
        // TODO: Demonstrate the Command Pattern:
        // 1. Set a TVOnCommand and press the button
        // 2. Set a TVChannelCommand with the input channel and press the button
        // 3. Set a ThermostatSetCommand with the input temperature and press the button
        // 4. Set a TVOffCommand and press the button
        
        scanner.close();
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming