The Command Pattern is a behavioral design pattern that encapsulates a request as an object, allowing requests to be parameterized, queued, logged, or undone independently of the object that executes them.

Instead of invoking methods directly on a receiver object, the client creates a command object that represents the requested operation. An invoker executes the command without knowing how the operation is actually performed.

This separation decouples the object that issues a request from the object that performs it, making the system more flexible and extensible.

The Command Pattern is commonly used for undo/redo functionality, task scheduling, job queues, GUI actions, and remote command execution.

Structure

The Command Pattern consists of the following participants.

1. The Command declares the interface for executing an operation.
2. The Concrete Command implements the command interface and delegates work to the receiver.
3. The Receiver performs the actual business operation.
4. The Invoker triggers command execution without knowing its implementation.
5. The Client creates the command and associates it with the receiver.

Java Implementation

Suppose an application controls smart home devices. A remote control should be able to switch different devices on without knowing how each device performs the operation.

Create the command interface.
public interface Command {
    void execute();
}
Create the receiver.
public class Light {
    public void turnOn() {
        System.out.println("Light turned on.");
    }
}
Create the concrete command.
public class TurnOnLightCommand implements Command {
    private final Light light;

    public TurnOnLightCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOn();
    }
}
Create the invoker.
public class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}
The client configures the invoker.
public class Main {
    public static void main(String[] args) {
        Light light = new Light();
        Command command = new TurnOnLightCommand(light);

        RemoteControl remote = new RemoteControl();
        remote.setCommand(command);
        remote.pressButton();
    }
}
Output:
Light turned on.

How It Works?

The client first creates the Light object, which acts as the receiver responsible for performing the actual operation.

A TurnOnLightCommand object is then created with a reference to the receiver. The command encapsulates the request and knows how to invoke the receiver's operation.

The RemoteControl acts as the invoker. It simply executes the assigned command by calling its execute() method without knowing what operation is being performed.

This design allows the same invoker to execute different commands, such as turning lights off, opening garage doors, or starting appliances, without requiring any changes to the invoker itself.

Advantages

1. It decouples the object that issues a request from the object that executes it.
2. Commands can be queued, scheduled, logged, or executed remotely.
3. It simplifies the implementation of undo and redo operations.
4. New commands can be introduced without modifying existing client or invoker code.

Disadvantages

1. The pattern introduces additional command classes.
2. Simple operations may require unnecessary boilerplate code.
3. Managing many command objects can increase application complexity.

JDK Examples

The Command Pattern appears throughout the Java ecosystem.

1. The java.lang.Runnable interface represents a command whose run() method encapsulates an executable task.

2. The javax.swing.Action interface encapsulates user interface actions such as button clicks and menu selections, allowing them to be executed by different UI components.

Summary

The Command Pattern encapsulates a request as an object, separating the object that invokes an operation from the object that performs it.

By representing operations as command objects, the pattern enables flexible request handling, task scheduling, undo functionality, and improved decoupling between application components.
Nagesh Chauhan

Nagesh Chauhan

Principal Software Engineer • Java • Python • Distributed Systems • AI/ML

Principal Software Engineer with 14+ years of experience designing and delivering large-scale distributed systems, cloud-native applications, and AI-powered platforms.

Passionate about solving complex engineering problems using strong data structures and algorithms, along with expertise in Java, Spring Boot, Python, System Design, Microservices, Cloud, Kafka, Elasticsearch, and Generative AI.

Share this Article

💬 Comments

Join the Discussion