The Command Pattern is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request.
This transformation lets you pass requests as a method arguments, delay or queue a request's execution, and support undoable operations.
The Problem
Imagine you are building a Customizable Toolbar for your IDE. You have several buttons (Save, Copy, Paste). If you hardcode the logic for "Saving" directly into the Button class, you can't reuse that button for a "Copy" function. Furthermore, if you want to implement a "Global Undo" feature, the app has no way of knowing what the last action was because the logic was hidden inside a button click.
The Solution: The Command Object
Instead of the button doing the work, the button holds a Command object. When you click the button, it simply calls command.execute(). The button doesn't need to know what the command does; it just knows how to trigger it.
Step-by-Step Java Implementation
1. The Command Interface
All commands must have an execute method (and optionally an undo method).
// Command.java
public interface Command {
void execute();
void undo();
}
2. The Receiver
The class that actually knows how to perform the business logic.
// Light.java
public class Light {
public void turnOn() { System.out.println("The light is ON"); }
public void turnOff() { System.out.println("The light is OFF"); }
}
3. Concrete Commands
Classes that bind a receiver to an action.
// LightOnCommand.java
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
@Override
public void execute() { light.turnOn(); }
@Override
public void undo() { light.turnOff(); }
}
Full Code for Testing
This example includes a "Remote Control" (the Invoker) that can store and undo commands.
// Save as CommandTest.java
import java.util.Stack;
// 1. Command Interface
interface Command {
void execute();
void undo();
}
// 2. Receiver
class TextEditor {
private String text = "";
public void write(String input) { text += input; }
public void deleteLast(int length) {
text = text.substring(0, text.length() - length);
}
public void show() { System.out.println("Current Text: " + text); }
}
// 3. Concrete Command
class WriteCommand implements Command {
private TextEditor editor;
private String textToWrite;
public WriteCommand(TextEditor editor, String text) {
this.editor = editor;
this.textToWrite = text;
}
@Override
public void execute() { editor.write(textToWrite); }
@Override
public void undo() { editor.deleteLast(textToWrite.length()); }
}
// 4. Invoker
class UserHistory {
private Stack<Command> history = new Stack<>();
public void executeCommand(Command cmd) {
cmd.execute();
history.push(cmd);
}
public void undoLast() {
if (!history.isEmpty()) {
Command cmd = history.pop();
cmd.undo();
}
}
}
// 5. Client
public class CommandTest {
public static void main(String[] args) {
TextEditor myDoc = new TextEditor();
UserHistory history = new UserHistory();
System.out.println("--- Command Pattern: Text Editor Test ---");
// Action 1: Write "Hello "
Command writeHello = new WriteCommand(myDoc, "Hello ");
history.executeCommand(writeHello);
myDoc.show();
// Action 2: Write "World!"
Command writeWorld = new WriteCommand(myDoc, "World!");
history.executeCommand(writeWorld);
myDoc.show();
// Action 3: Undo
System.out.println("\n[Action] Clicking Undo...");
history.undoLast();
myDoc.show();
System.out.println("\n--- Test Complete ---");
}
}
Why use Command?
- Undo/Redo: Since every action is an object, you can store them in a list or stack to reverse them.
- Deferred Execution: You can schedule commands to run at a specific time or queue them up.
- Decoupling: The object that triggers the command (the Button) is completely separate from the object that performs the logic (the Editor).
Real-World Example
- GUI Buttons: In Java Swing or JavaFX,
ActionListenersare a form of the command pattern. - Transactions: Database systems often use command objects to "Journal" actions so they can be rolled back if a crash occurs.