Command pattern

Command pattern

Definition

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Introduction

Communication between objects in enterprise applications starts from an object sending a request to another object. The object receiving the request can either process the request and send back a response or forward the request to another object for processing. Typically requests are made by the invoker (the object making the request) through method calls on the object that processes the request, which we will refer as the receiver. As a result, the invoker and the receiver are tightly coupled. This violates the SOLID design principles that advocates loosely coupled components to ensure that changes made to one component does not affect the other components of the application.

The Command Pattern is a proven solution that addresses such recurring problems of tightly coupled invoker and receiver components in applications. This pattern states that requests should be encapsulated as objects that like any other objects can be stored and passed around the application. Requests encapsulated as objects are known as commands.

In the command pattern, the invoker issues command without knowing anything about the receiver. In fact, the invoker issuing the command doesn’t even know what operation will be carried out on issuing a command. Let’s look at it from a programming point of view.

A command object basically has a execute() method and an optional undo() method. The execute() method executes some operation on the receiver while the undo() method reverses the current operation. The implementation of the operation is done by the receiver. The invoker only sets itself up with a command object and invokes a command by calling the execute() method. The invoker does not know what the execute() method will do.

Imagine that the invoker is a switch, When the invoker invokes a command by calling the execute() method of a command object, it might turn on a light or even start a generator. What this essentially means is that the same invoker (switch) can be used to invoke commands to perform actions on different receivers (devices). We only need to create the appropriate command object and set it on the invoker. As apparent, by applying the Command Pattern we can take reusability to another level and this is made possible due to the loose coupling between the invoker and receiver and the command object that acts as the interface between them.

Analogy

Before drilling into the participants of the Command Pattern and their roles, let’s start with an analogy of remote-controlled toys.

Imagine a toy manufacturing company, which recently decided to manufacture remote-controlled toys. They started with a remote-controlled car. The remote control has three buttons: On, Off, and Undo. The remote control is programmed so that the On button moves the car, the Off button stops it, and the Undo button reverses the current action of the car. The remote-controlled car was a success and the management next decided to manufacture a remote controlled rotating top. Again, along with the top, a new remote control programmed to start and stop rotating and reverse the current action of the top was manufactured. Riding on the success of remote-controlled toys, the management decided to manufacture 200 varieties of remote controlled toys each with a remote control programmed differently to operate its corresponding toy. Imagine yourself in the programming team. You need to create 200 different programs for the remote controls each designed to operate on a specific toy. Apparently a bad design decision because of the inability to reuse code. The reason is also apparent. Each remote control is tightly coupled with the toy it operates on. What we need is a remote control that is programmed to operate on all the toys, and here is where the Command Pattern comes to the rescue.

Let’s look how we can apply the pattern as a solution. The toys are the receivers and perform actions. Let us model two receivers as Car and RotatingTop. These classes have behaviors in the form of methods to perform actions. For example, the Car receiver will have methods to move and stop and the RotatingTop will have methods to start and stop rotating.

We will next model the commands that will trigger the actions on the receivers. We start with a CommandBase interface with two methods execute() and undo(). Each concrete sub classes of CommandBase represents a command to trigger an action on the receiver, and to do so it maintains a reference to the receiver whose action it will trigger. For the Car and RotatingTop receivers, let us model the concrete command classes as CarMoveCommand, CarStopCommand, TopRotateCommand, and TopStopRotateCommand. Finally we will model the invoker as a RemoteControl class. This class is not aware of any concrete command class. Whenever one of its button is pressed, the method handling the press event is injected with an appropriate command object at runtime and the invoker calls the execute() method on it.

Participants

  1. Command (CommandBase): Is an interface for executing an action.
  2. ConcreteCommand (CarMoveCommand, CarStopCommand, TopRotateCommand, and TopStopRotateCommand): Are concrete classes that implements Command and defines the execute() and undo() methods to communicate with receivers for performing an action and undoing it respectively.
  3. Invoker(RemoteControl): Asks Command to carry out the action.
  4. Receiver (Car and RotatingTop): Performs the action based on the command it receives.
  5. Client: Creates a ConcreteCommand object and sets its receiver.

Summary

Beginning programmers may find the Command Pattern daunting. They may not have the vision nor experience to see how it applies to common programming tasks. The Command Pattern is commonly seen in GUI code, such as handling actions of buttons, menu items, action links and also Java progress bars and wizards. It is also seen in Runnable related code. But, this pattern is not limited to them. In developing web applications with Spring MVC, you often see the concepts of the Command Pattern applied through the use of Command Objects. Think about an e-commerce application where you are adding an item to your cart. That form post to add the item to your cart is effectively a “command”. Hence a core component of Spring MVC is the AbstractCommandController.

The Command Pattern isn’t just limited to Spring MVC. When developing enterprise applications using the Spring Framework, you will find plenty of other opportunities to apply the Command Pattern. Whenever you are writing code that requires some invoker to perform different actions on multiple receivers, consider using the Command Pattern – after all, it is one of the classic GoF design patterns.

Reading material

https://github.com/explorer436/programming-playground/tree/main/java-playground/design-pattern-samples/design-pattern-examples

  1. https://springframework.guru/gang-of-four-design-patterns/command-pattern/

Links to this note