What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
The Command design pattern turns an operation into an object: instead of calling a receiver directly, a caller passes a command that can be executed now or handled later. In Java, a small command interface and concrete command classes separate the object that triggers an action from the object that performs it. That separation is useful for buttons, queued jobs, and undoable actions, but adds unnecessary structure to a simple one-off call.
What is the Command design pattern?
Command is a behavioral design pattern that packages a request as a stand-alone object containing the information needed to carry it out. Refactoring.Guru describes it as turning “a request into a stand-alone object that contains all information about the request.” Because the request is an object, software can pass it as an argument, delay or queue execution, and in some cases support undo.
A direct method call couples the caller to the receiver’s API. With Command, the caller works through a command interface instead. This is valuable when the request needs a lifecycle—such as storing, scheduling, logging, retrying, or reversing it—rather than just an immediate method call.
How the pattern’s roles fit together
- Client: creates the receiver and concrete command, then connects the command to an invoker.
- Command: declares the operation the invoker can trigger, commonly through an
execute()method. - Concrete command: stores the receiver and any request parameters, then delegates the work when executed.
- Receiver: contains the domain logic that actually performs the operation.
- Invoker: triggers a command without needing to know the receiver’s concrete type or how the operation works.
The command object is the bridge: it knows both what should happen and which receiver should do it, while the invoker only knows how to call the command.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Implement a basic Command in Java
This example connects a button to a light. The button is the invoker, the light is the receiver, and TurnOnLight is the concrete command.
public interface Command {
void execute();
}
public final class Light {
public void turnOn() {
System.out.println("Light is on");
}
}
public final class TurnOnLight implements Command {
private final Light receiver;
public TurnOnLight(Light receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.turnOn();
}
}
public final class Button {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void press() {
if (command == null) {
throw new IllegalStateException("No command has been assigned");
}
command.execute();
}
}
public final class Example {
public static void main(String[] args) {
Light light = new Light();
Command turnOn = new TurnOnLight(light);
Button button = new Button();
button.setCommand(turnOn);
button.press();
}
}
The client wires the pieces together; pressing the button does not require button code to know about Light. The example’s null check makes the invoker’s unconfigured state explicit; another design could require a command in the button constructor instead.
Rank #2
How to add undo and redo
An executable command is not automatically undoable. To support undo, the command must retain enough information to restore the previous state or perform a meaningful compensating operation. For example, a command that changes a setting can record its old value before applying the new one.
Define an undoable contract
public interface UndoableCommand {
void execute();
void undo();
}
A concrete command can capture prior state during execution:
Free tools Windows power users keep installed
One-click scans. No signup required.
public final class SetBrightness implements UndoableCommand {
private final Display display;
private final int newBrightness;
private int previousBrightness;
private boolean executed;
public SetBrightness(Display display, int newBrightness) {
this.display = display;
this.newBrightness = newBrightness;
}
@Override
public void execute() {
previousBrightness = display.getBrightness();
display.setBrightness(newBrightness);
executed = true;
}
@Override
public void undo() {
if (!executed) {
throw new IllegalStateException("Cannot undo before execution");
}
display.setBrightness(previousBrightness);
}
}
Here, Display represents a receiver with getBrightness() and setBrightness(int) methods. A history manager can push a command only after its execution succeeds; undo then removes the newest command and calls undo(). Redo usually requires a second stack: move a successfully undone command to it, and move it back to the undo history after re-execution. Clear the redo stack when a new command is executed after undo, since that creates a different action sequence.
For compound operations, undo must account for partial failure. If execution changes several pieces of state and fails midway, the command or transaction layer needs a defined recovery strategy; blindly adding the command to history can make later undo incorrect.
Rank #4
When an inverse operation is not true undo
Some actions cannot be rolled back. A sent email cannot be unsent, and an external service may not support reversal. A command can sometimes issue a compensating action—such as sending a correction or refund—but that is not the same as restoring the world to its exact earlier state. Treat such commands as non-undoable unless the domain provides a reliable compensation path.
When Command is useful—and when it is not
Good fits
- GUI buttons, menus, and keyboard shortcuts that should trigger different operations through a common interface.
- Background jobs, queues, and schedulers where requests need to be stored and run later.
- Retryable work, provided the operation is safe to retry or includes protection against duplicate effects.
- Macro commands that compose several actions into one user-triggered operation.
- Undo histories, audit records, or transaction workflows that need to represent operations as data.
Prefer a direct call for a simple request
If one object immediately calls one method and there is no need to queue, reuse, log, compose, retry, or undo the request, a command class may add indirection without solving a real problem. The pattern also creates decisions about command state and history lifetime: whether commands are reusable, how long references to receivers remain valid, and what happens when a queued request becomes stale.
Best Value
Command compared with a direct method call
| Concern | Direct method call | Command pattern |
|---|---|---|
| Request lifetime | Usually runs immediately at the call site. | Can be represented as an object and stored or run later. |
| Caller and receiver coupling | Caller invokes a particular receiver API directly. | Invoker depends on the command interface; concrete command delegates to receiver. |
| Operational control | Queueing, retrying, composing, or undoing requires separate mechanisms. | Request object can be queued, logged, retried, composed, or integrated into undo handling. |
| State and side effects | Call site’s structure does not itself capture prior state. | Command can retain prior state or define compensation, but reversibility depends on the operation. |
| Complexity | Less indirection for a one-off operation. | Adds command types and possibly history management. |
Design checks before using Command
- Keep the command interface focused on the action the invoker needs; do not expose receiver-specific details through it.
- Put domain behavior in the receiver where practical, rather than turning every concrete command into a second copy of business logic.
- Decide whether commands are one-shot or reusable. Commands that capture changing prior state are generally safer as one-shot history entries.
- Define what counts as successful execution before adding a command to undo history.
- For queued work, decide how to handle retries, duplicate delivery, stale parameters, and receiver availability.
- For audit logs, distinguish a record of an attempted request from a record of a successfully completed operation.
- Document whether undo restores prior state or performs a compensating action.
Further reading
The pattern’s catalog description and a worked Java example are available from Refactoring.Guru’s Command pattern guide and Java example. For the broader design-pattern catalog, see Patterns.dev’s Command pattern overview.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

