Java > Design Patterns in Java > Behavioral Patterns > Command Pattern
Command Pattern Example: Remote Control
This example demonstrates the Command Pattern using a simple remote control scenario. The remote control can turn on and off a light.
Introduction to the Command Pattern
The Command Pattern encapsulates a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. It promotes loose coupling between the object issuing the request (the invoker) and the object that knows how to perform the request (the receiver).
Components of the Command Pattern
The Command Pattern typically involves these components:
Command Interface
This interface declares the `execute()` method that all concrete command classes will implement. The `undo()` method is added for making commands undoable.
interface Command {
void execute();
void undo();
}
Receiver: The Light Class
This class represents the receiver of the command. It has `turnOn()` and `turnOff()` methods to control the light.
class Light {
private boolean isOn = false;
public void turnOn() {
isOn = true;
System.out.println("Light is ON");
}
public void turnOff() {
isOn = false;
System.out.println("Light is OFF");
}
public boolean isOn() {
return isOn;
}
}
Concrete Command: TurnOnCommand
This class implements the `Command` interface and holds a reference to the `Light` object. The `execute()` method calls the `turnOn()` method of the `Light` object. The `undo()` method calls the `turnOff()` method.
class TurnOnCommand implements Command {
private Light light;
public TurnOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
@Override
public void undo() {
light.turnOff();
}
}
Concrete Command: TurnOffCommand
This class implements the `Command` interface and holds a reference to the `Light` object. The `execute()` method calls the `turnOff()` method of the `Light` object. The `undo()` method calls the `turnOn()` method.
class TurnOffCommand implements Command {
private Light light;
public TurnOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
@Override
public void undo() {
light.turnOn();
}
}
Invoker: The RemoteControl Class
This class represents the invoker. It holds a `Command` object and executes the command when the `pressButton()` method is called. It also has the `pressUndo` method to undo the last command.
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
Client: Putting it all together
This is the client code that creates the `Light`, `Command`, and `RemoteControl` objects and connects them. It then uses the `RemoteControl` to execute the commands.
public class CommandPatternExample {
public static void main(String[] args) {
Light light = new Light();
Command turnOnCommand = new TurnOnCommand(light);
Command turnOffCommand = new TurnOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(turnOnCommand);
remote.pressButton(); // Light is ON
remote.setCommand(turnOffCommand);
remote.pressButton(); // Light is OFF
remote.pressUndo(); //Light is ON - undo the last command
}
}
Concepts behind the Snippet
This snippet illustrates how the Command pattern decouples the invoker (RemoteControl) from the receiver (Light). The invoker doesn't need to know the specifics of how the light is turned on or off. It only knows that it can execute a Command object. This makes the code more flexible and easier to maintain. The `undo()` method demonstrates how the command pattern can support undoable operations.
Real-Life Use Case Section
The Command pattern is used in various real-world scenarios, such as:
Best Practices
Interview Tip
Be prepared to explain the benefits of the Command pattern, such as decoupling, flexibility, and support for undoable operations. You should also be able to provide real-world examples of how the pattern is used.
When to use them
Use the Command pattern when:
Memory Footprint
The Command Pattern can increase memory usage due to the creation of command objects. Each command object stores the necessary information to execute the request. In scenarios with many commands, this can become a concern. Evaluate if the decoupling benefits outweigh the memory overhead.
Alternatives
Alternatives to the Command Pattern include:
Pros
Cons
FAQ
-
What is the main benefit of using the Command Pattern?
The main benefit is decoupling the invoker from the receiver. This allows you to change the way a request is handled without modifying the invoker. -
How does the Command Pattern support undoable operations?
By implementing an `undo()` method in the `Command` interface, you can reverse the effects of the `execute()` method.