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 is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request. This transformation lets you parameterize methods with different requests, delay or queue a request's execution, and support undoable operations.
[Image: Command Pattern Class Diagram]
<!-- Add a class diagram image here -->
-
Command Interface
- Declares an interface for executing an operation
- Contains methods like
execute()andundo()
-
Concrete Commands
- Implements the Command interface
- Defines a binding between a Receiver object and an action
- Implements
execute()by invoking the corresponding operation(s) on the Receiver
-
Receiver
- Knows how to perform the operations associated with carrying out a request
- Any class can serve as a Receiver
-
Invoker
- Asks the command to carry out the request
- Holds commands and can execute them
- Can also support undo operations
-
Command.javapublic interface Command { void execute(); void undo(); void show(); }
-
LightOnCommand.javaandLightOffCommand.java- Concrete command implementations
- Encapsulate the receiver (Light) and the action to perform
-
Light.java- The receiver class
- Knows how to perform the actual operations
// Create the receiver
Light light = new Light();
// Create the commands
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
// Execute commands
lightOn.execute(); // Turns the light on
lightOff.execute(); // Turns the light off
lightOn.undo(); // Undoes the last commandThe Command pattern is particularly useful when:
- You need to parameterize objects with operations
- You want to queue operations, schedule their execution, or execute them remotely
- You need to implement undo/redo functionality
- You want to structure a system around high-level operations
- You need to support logging and transactions
- Decouples the invoker from the receiver
- Allows for command queuing and logging
- Supports undo/redo operations
- Enables the implementation of complex operations
- Provides a way to parameterize clients with different requests
- Can lead to a large number of command classes
- May increase the complexity of the code
- Can be overkill for simple operations
-
Text Editor
- Undo/redo operations
- Copy/paste commands
- Formatting commands
-
Remote Control
- Button presses mapped to commands
- Macro commands for multiple operations
- Undo functionality
-
Job Queue Systems
- Command queuing
- Asynchronous execution
- Command logging
- Composite: Can be used to implement macro commands
- Memento: Can be used to implement undo/redo
- Observer: Can be used to implement command logging
- Strategy: Similar in structure but different in intent
- Keep commands focused and simple
- Use the Command pattern when you need to:
- Queue operations
- Support undo/redo
- Log operations
- Implement remote execution
- Consider using the Composite pattern for macro commands
- Use the Memento pattern for implementing undo/redo
- Consider thread safety in multi-threaded environments
When testing Command pattern implementations:
- Test each command in isolation
- Verify undo/redo functionality
- Test command queuing
- Verify command logging
- Test macro commands
- Verify thread safety
- Creating too many command classes
- Overcomplicating simple operations
- Not properly implementing undo/redo
- Ignoring thread safety
- Not considering command queuing
- Not implementing proper error handling
- Add support for command queuing
- Implement command logging
- Add support for macro commands
- Implement remote execution
- Add support for command scheduling
- Implement command persistence