HFDP(6) - Command Pattern
Published: 2023-01-18 02:22:53

In this post we discuss the Command Pattern. 

Say the IoT is really getting its trend. A company has designed a set of electronics like `Light`, `GarageDoor`, `CeilingFan` etc., that could be controlled by a program. Now you want to design an app for the client (the house owner, the resident), how should you hide the details of the electronics, while making it flexible enough for the client to customize their needs?

To better appreciate the problem, imagine you are a resident. Wouldn't it be nice to have a remote controller, which allows you to open/close light by simply pressing a button? Or make the garage door up/down, or make the ceiling fan on/off by simply pressing a button? But you do not want to go into the dirty details of each class: yeah, to turn the light on, somewhere needs to call `light.on()`; to open the garage door, somewhere needs to call `garageDoor.up()`... But it should not be our lovely, innocent clients to call them, right? We just want to hide the details and reduce coupling. What if at one time we have renamed `light.on()` api to `light.turnOn()`? Then the client has to change their code, which is probably the last thing we want it to happen! 

Luckily, questions like this have been encountered many times, there are sound wisdoms to the rescue. Let's introduce the protagonist of today: the **Command Pattern**. 

## Formal Definition 

> The **Command Pattern** encapsulates a request as an object, thereby letting you parametrize other objects with different requests, queue or log requests, and support undoable operations. 


## Class Diagram 
![Command Pattern](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uqzxe7yqnuymqvooc1s7.png)

What consists of the command pattern? an interface called `Command` that supports `execute()` and `undo()`; `ConcreteCommand` that implements `Command` interface and binds `Receiver` with its `action()`; An `Invoker` that will call `execute()` of a certain command; Lastly, of course our Client, which should create a `ConcreteCommand` and setting its `Receiver`. 

## Explained in a real example 
To make things less abstract, let's go back to our example of `Light`, `GarageDoor` etc. We will have an interface `Command`. As for the `ConcreteCommand`, we may have `TurnLightOnCommand` class, which should be initialized with a `Light` instance (`Receiver`), inside its `execute()` method, it writes something like `public void execute() {light.on();}`. Similar logic goes for `undo()` method. Other classes that implements `Command` include `TurnLightOffCommand`, `OpenGarageDoorCommand`, `CloseGarageDoorCommand`. What the client (again, resident of the house) should do is to create a concrete command and set its receiver (`TurnLightOnCommand` and `lightInLivingRoom`). The remote controller would be the `Invoker`. The user should put their commands to corresponding buttons (put `turnLightInLivingRoomCommand` to button 1, for example.) 


![remote controller](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hmjhkm2mogckofwns8vf.png)

## A less down-to-earth but relevant example 

Imaging a job queue: you add commands to the queue. The queue will finish command one by one. The command may be financial computation, network requesting, etc., but the queue does not need to know which one is which, because they all have implemented interface `Command` so have `execute()`, the queue just needs to invoke that method. 


That's the big picture of the Command Pattern. See you next design pattern!