Design Pattern — Command Design Pattern Simplified
There are many Command pattern explanation out there, but I found it a bit difficult to digest or understand the example provided in those blogs/posts.
So, here I will try to explain in the way I understood.
To understand command pattern lets go back to 1990s when we had huge TVs without a remote(at least in India). Good old days ;)
We had all the knobs for on/off, increase/decrease volumes.
Everything was good, working fine, the only problem was if anyone wanted to switch the TV on/off or reduce/increase volume, they had to go all the way to the TV and use the knob.
Now think this in an object-oriented way. A TV is an object which has a bunch of operations/methods/functions or “Command”. We are directly accessing the TV object to invoke these commands.
The problem with this approach?
- You need the object to invoke a command — hence walk all the way to the TV
- Every TV has its own implementation of start/stop and we are not able to re-use the “Command invocation”
- If another device say “Set-Top Box” wants the same functionality, no way to re-use the same operations — “Universal Remote”
How can we solve this?
Imagine the TV has an interface that implements on/off and other functionality and exposes these methods/operations, by giving the instance of the interface to an “another object”. That could solve our problem. Let’s get into code:
First, we will create a TV class, which have the operations on/off.
Likewise, we will create a Set-top box class as we are creating a universal remote.
Now that we have defined our devices and its operations, we need a class(Command) that can keep objects of TV/SetTopBox and invoke these operations.
Let’s create our command class. As we want to perform two operations on these devices, the Command class will “have” an object of IDevice type.
We need two commands “ON” and “OFF”.
These On/Off command objects will have one execute function/method, which will invoke the respective operation on the device it has.
If you have noticed, I have created the classes with the name “OnCommad” and not “TVOnCommand”. The idea is to re-use the command class for different devices. That’s our universal command, which supports any device.
This will enable us to create a universal remote. Bingo!!!!
Till now, we have abstracted out the device operations in the form of “Command”. The only thing remaining for us is to create a RemoteControl, to trigger the “command”.
Before we create remote control, we need to create buttons and each button will execute the respective command.
The RemoteButton class has a command object, which is executed when the button is pressed.
Finally, let's create our Remote Control Device, which will have multiple buttons for each operation.
When we are creating a remote control device(using constructor), we will instantiate all the objects and assign.
If you look at the above code, we have defined multiple buttons in our Remote and we are trying to make Universal remote.
We are all set to create and play with our RemoteControlDevice :)
Output:
TV is on!
TV is off!
SetTopBox is on!
SetTopBox is off!Process finished with exit code 0
As seen in output I have pressed different buttons, to perform a set of operations on the Devices.
So, in short, the idea is to give the client(psvm/TV user) a remote instead of making them walk all the way to TV or give TV to turn on/off TV :D
Conclusion
In this post, we talked about the Command design pattern.
In simple words:
The idea is to encapsulate the operations in a different object(Command) and re-use and then create several buttons to execute these command objects which has Device operations in it.
As usual, you can find all the code on my GitHub.