Command Pattern
What
Encapsulates a request as an object, allowing parameterization of clients with queues, logs, and undoable operations.
When
- You want to decouple the sender of a request from the object that performs it.
- Support for operations like undo, logging, or queueing is needed. You want to encapsulate requests, e.g., for undo/redo or UI buttons.
class Light {
public void turnOn() {
System.out.println("Light on");
}
}
class Remote {
private Light light = new Light();
public void buttonPressed() {
light.turnOn(); // Remote is tightly coupled to specific action
}
}
How
- Define a
Command
interface with anexecute()
method. - Create concrete command classes that implement
Command
and call methods on a receiver. - Invoker stores command objects and calls
execute()
.
interface Command { void execute(); }
class Light {
public void turnOn() { System.out.println("Light on"); }
}
class TurnOnCommand implements Command {
private Light light;
public TurnOnCommand(Light l) { this.light = l; }
public void execute() { light.turnOn(); }
}
class Remote {
public void press(Command c) { c.execute(); }
}
Examples
- GUI buttons triggering commands (e.g., copy, paste, save)
- Transaction queue in a banking app
- Undo functionality in a text editor
Why
Advantages
- Decouples sender and receiver
- Adds support for undo/redo, logging, and queuing
- Commands can be parameterized and reused
Disadvantages
- Can lead to many small classes
- Extra layer of indirection