Also known as Action, Transaction.
As stated in GoF, p233 :
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
In a few words :
- An object that represents a request (an operation)
- Contains all the necessary information for the request to be taken.
You should use the Command pattern in the following cases :
- Parameterize objects by an action to perform (just like callback functions in procedural languages).
- Specify, order, queue and execute requests at different times (even remotely).
- You want to implement reversible commands.
Examples of use
- GUI Commands
- Multi-level do/undo/redo
- ...
Command VS Query
- A Command is asking an object for a change and therefore induces a mutation of that object.
- A Query asks an object for informations - it does not change the object.
Participants
- Command : Interface defining two operations
- do()
- undo()
- ConcreteCommand : Implements Command interface by invoking the corresponding operation(s) on the Receiver.
- Client : Creates ConcreteCommands and sets their Reveiver.
- Invoker : Asks the Command to carry out the request.
- Receiver : Knows how to perform the operations associated with carrying out a request.
How to implement
- Declare the Command interface with do() undo() operations.
- Extract request into ConcreteCommands classes that implement Command interface.
- Identify classes that will act as senders. Add fields for storing commands into these classes.
- Change the senders so they execute the command instead of sending a request to the receiver directly.
Note : Invoker should communicate with their commands only via the Command interface. Invokers usually do not create Commands on their own but rather receive them from the Client.
Note : UML class diagram taken from here
Pros
- Separation of concerns principle : Classes that invoke operations are decoupled from the one that perform the operations.
- Open/Closed principle : Pretty easy to introduce new ConcreteCommands without breaking any existing Client code. -Composition : Create complex command by assembling a set of simple commands.
- Do/Undo operations.
Cons
- Complexity : The code might become more complicated with the multiplication of classes. Also you just introduced a layer between senders and receivers.
Here are some usefull ressources :
- w3sdesign
- A Refactoring guru article.
- A complete example on bogotobogo
