Overview
The Command Design Pattern encapsulates a request as an object, thereby allowing for parameterization of clients with different requests, queuing of requests, and logging of the requests. It also provides support for undoable operations.
Key Characteristics
- Encapsulates a request as an object.
- Promotes decoupling between the sender and receiver of the request.
- Supports queuing, logging, and undoing of commands.
Implementation
The following is an example of a Command implementation in Java:
// Command interface
interface Command {
void execute();
void undo();
}
// Receiver
class Light {
public void turnOn() {
System.out.println("The light is ON");
}
public void turnOff() {
System.out.println("The light is OFF");
}
}
// Concrete Command
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();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
@Override
public void undo() {
light.turnOn();
}
}
// Invoker
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
// Demo
public class CommandDemo {
public static void main(String[] args) {
Light livingRoomLight = new Light();
Command lightOn = new LightOnCommand(livingRoomLight);
Command lightOff = new LightOffCommand(livingRoomLight);
RemoteControl remote = new RemoteControl();
// Turn the light ON
remote.setCommand(lightOn);
remote.pressButton();
// Turn the light OFF
remote.setCommand(lightOff);
remote.pressButton();
// Undo the last action
remote.pressUndo();
}
}
When to Use
- When you want to parameterize objects with operations.
- When you need to support undo and redo operations.
- When you want to log operations or delay their execution.
Advantages
- Promotes loose coupling between the invoker and the receiver.
- Allows easy implementation of undo and redo functionality.
- Supports queuing and logging of commands.
Disadvantages
- Can lead to an increase in the number of classes in the codebase.