1. Definition
The Command design pattern encapsulates a request as an object, allowing for parameterization of clients with different requests, queuing of requests, and logging the operations. It also provides support for undoable operations.
2. Problem Statement
Imagine needing to implement operations that require undo/redo functionality, or you need to delay, schedule, or log operations. Directly implementing these requirements can result in a complex, hard-to-maintain codebase.
3. Solution
The Command pattern suggests that GUI objects (like buttons, menus, etc.) shouldn’t send requests directly. Instead, they should delegate the work to a separate command object which performs the operation.
4. Real-World Use Cases
1. In GUI libraries, where each action of a menu or button is encapsulated as a command object.
2. Undo and redo functionalities in software like word processors or graphic editors.
3. Operation scheduling, like job queues.
5. Implementation Steps
1. Define a command interface with an execute method.
2. Create one or more derived classes that encapsulate some core logic or action as a command.
3. Define classes that act as invokers, and they can issue the command.
6. Implementation in Java
// Command interface
interface Command {
void execute();
}
// LightReceiver Class
class Light {
public void on() {
System.out.println("Light is ON");
}
public void off() {
System.out.println("Light is OFF");
}
}
// Concrete Command classes
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
// Invoker Class
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// Client
public class Client {
public static void main(String[] args) {
Light light = new Light();
RemoteControl control = new RemoteControl();
// Switch on the light
control.setCommand(new LightOnCommand(light));
control.pressButton();
// Switch off the light
control.setCommand(new LightOffCommand(light));
control.pressButton();
}
}
Output:
Light is ON Light is OFF
Explanation:
The Light class (receiver) has methods to turn it on and off. The LightOnCommand and LightOffCommand classes (concrete commands) encapsulate these actions as commands. The RemoteControl class (invoker) can be set with a command and execute it when its method pressButton is called.
7. When to use?
1. When you need to parameterize objects with operations.
2. When you need to queue operations, schedule their execution, or execute them remotely.
3. When you need to support undo and redo actions.