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.
The Command Pattern decouples the object that invokes the operation from the one that knows how to perform it. Commands encapsulate actions and their receivers.
- Command: Interface declaring an execute method
- ConcreteCommand: Implements the Command interface and defines the binding between a Receiver and an action
- Receiver: The object that performs the actual work when the command's execute() is called
- Invoker: Holds a command and calls its execute() method (e.g., RemoteControl)
- Client: Creates ConcreteCommand objects and sets their receivers
Demonstrates a home automation remote control using the Command Pattern to control lights, garage doors, ceiling fans, and other devices.
See the BasicRemote README for compilation and execution details.
Shows a modern Java implementation using lambda expressions to simplify command creation.
See the LambdaRemote README for compilation and execution details.
From the parent directory of CommandPattern:
javac -d out CommandPattern/BasicRemote/*.javaOr for the lambda example:
javac -d out CommandPattern/LambdaRemote/*.javajava -cp out CommandPattern.BasicRemote.RemoteControlTestOr for the lambda example:
java -cp out CommandPattern.LambdaRemote.RemoteControlTest- Decoupling: Decouples the object making the request from the object that knows how to perform it
- Flexibility: Commands can be assembled into composite commands
- Extensibility: New commands can be added without changing existing code
- Undo/Redo: Commands can store state for reversing their effects
- Queuing: Commands can be queued for later execution
- Logging: Commands can be logged for audit trails or crash recovery
Use the Command Pattern when:
- You need to parameterize objects with operations
- You need to queue operations, schedule their execution, or execute them remotely
- You need to support undo/redo functionality
- You need to structure a system around high-level operations built on primitive operations
- You need to log changes so they can be reapplied in case of a system crash