In this article, we will learn how to use Command pattern. Let’s get started.
Table of Contents
- Given Problem
- Solution with Command Pattern
- When to use
- Benefits & Drawbacks
- Relations with other patterns
- Application & Examples
- Wrapping up
Assuming that we are working in GUI application, we have multiple menu items, context menus, or buttons in toolbars in our apps. Normally, we will do something like that:
We coped with about hard-wired request:
receiver.doAction()is implemented (hard-wired) directly within the class - Invoker.
This makes it impossible to specify a request at run-time.
When designing reusable objects, the particular request is not known at compile-time and should be specified at run-time.
Solution with Command Pattern
According to Gang of Four’s definition, we have:
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Below is the class diagram of Command pattern:
Command pattern has primarily four components:
It will store all information that is required for executing an action, including the method to call, the method arguments, and the object (consider as Receiver) that implements the method.
This is actual object which do perform request when the command’s
execute()method is called.
It stores all commands and call
execute()method of Command object when necessary.
It knows how to execute a given command but does not know how the command has been implemented. It only knows about the command’s interface.
It has functionalities such as encapsulating each request into Command object, controls the command execution process by specifying what commands to execute and at what stages of the process to execute them.
When to use
- A history of requests is needed.
- We need callback functionality.
- Requests need to be handled at variant times or in variant orders.
- The invoker should be decoupled from the object handling the invocation.
Benefits & Drawbacks
It decouples the classes that invoke the operation from the object that knows how to execute the operation.
It allows us to create a sequence of commands by providing a queue system.
Extensions to add a new command is easy and can be done without changing the existing code.
We can also define a rollback system with the Command pattern.
There are a high number of classes and objects working together to achieve a goal. Application developers need to be careful developing these classes correctly.
Every individual command is a
ConcreteCommandclass that increases the volumne of classes for implementation and maintaince.
To refer this pattern’s code, we can read this link.
Relations with other patterns
Mementowork together when implementing undo operations.
Chain of Responsibility,
Observeraddress various ways of connecting senders and receivers of requests:
Chain of Responsibilitypasses a request sequentially along a dynamic chain of potential receivers until one of them handles it.
Commandestablishes unidirectional connections between senders and receivers.
Mediatoreliminates direct connections between senders and receivers, forcing them to communicate indirectly via a mediator object.
Observerlets receivers dynamically subscribe to and unsubscribe from receiving requests.
Strategy and Command pattern
Strategy pattern provides a way to configure an object with an algorithm at run-time instead of committing to an algorithm at compile-time.
Command pattern provides a way to configure an object with a request at run-time instead of committing to a request at compile-time.
Application & Examples
Undo/redo operations: The command pattern allows us to store the command object in a queue. This way, we can implement undo and redo operations.
Composite commands: Complex commands can be composed of simple commands using the composite pattern, and are run in a sequential order. In this way, we can build macros in an object-oriented-design manner.
The asynchronous method invocation: The command pattern is used in multithreading applications. Command objects can be executed in the background in separate threads. The java.lang.Runnable is a command interface.
Java 8 adds lambda expressions.
So, we do not need an object wrapper. All we need is to pick a functional interface.
Runnableis frequently a good choice.
In Apache struts 2 framework
Controllers are classes that extend
Actionhas a single method called
execute(). Framework collected
Actioninstances and invoked
execute()method as needed.
Thanks for your reading.