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
- Code C++/Javascript
- Relations with other patterns
- Application & Examples
- Wrapping up
Given Problem
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:
-
The 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:
-
Command
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.
-
Receiver
This is actual object which do perform request when the command’s
execute()
method is called. -
Invoker
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.
-
Client
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
-
Benefits
-
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.
-
-
Drawbacks
-
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
ConcreteCommand
class that increases the volumne of classes for implementation and maintaince.
-
Code C++/Java
To refer this pattern’s code, we can read this link.
Relations with other patterns
-
Command
andMemento
work together when implementing undo operations. -
Chain of Responsibility
,Command
,Mediator
andObserver
address various ways of connecting senders and receivers of requests:-
Chain of Responsibility
passes a request sequentially along a dynamic chain of potential receivers until one of them handles it. -
Command
establishes unidirectional connections between senders and receivers. -
Mediator
eliminates direct connections between senders and receivers, forcing them to communicate indirectly via a mediator object. -
Observer
lets 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.
Runnable
is frequently a good choice. -
In Apache struts 2 framework
Controllers are classes that extend
Action
.Action
has a single method calledexecute()
. Framework collectedAction
instances and invokedexecute()
method as needed.
Wrapping up
Thanks for your reading.
Refer:
https://dzone.com/articles/design-patterns-command
https://www.baeldung.com/java-command-pattern
Learn Python Design Patterns, Second Editor, By Chetan Giridhar