Table of Contents
What is the Command Pattern?
The definition of the Command Pattern from both Design Patterns: Elements of Reusable Object-Oriented Software and Head First Design Patterns: A Brain-Friendly Guide is
The Command Pattern encapsulates a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests, and support undoable operations.
Command Pattern Class Diagram Explained
The diagram shown above represents the generic class diagram of the Command Pattern. We start with the Command object. It is an interface with two method declarations Execute() and Undo() that will trigger the execution or undoing of the derived Command object, ConcreteCommand. The ConcreteCommand, implements the Command interface and is responsible for requesting any action on its Receiver object. The Client, is responsible for creating the ConcreteCommands and assigning its Receiver. The Invoker is responsible for calling the Command object to Execute(), not knowing the specific details of ConcreteCommand it is executing. Lastly, the Receiver understands the work necessary for performing the operation requested. The Receiver can be any class.
Command Pattern Example
In the spirit of the NCAA Basketball Final Four, I decided a simple basketball scoreboard would be a good program that could demonstrate the use of the Command Pattern. The scoreboard will only keep track of the score between two teams. So we would need some kind of scoreboard control to take input from a score keeper. Let’s call it BasketballScoreboardControl and consider it our Invoker class. On the controller, there is a button for each way you can score and an undo button. There are three ways to score in basketball, a free throw, a two point field goal and a three point field goal. Each of these will be a ConcreteCommand object that implements the Command interface. Let’s call them FreeThrowCommand, TwoPointFieldGoalCommand and ThreePointFieldGoalCommand, respectively. I had considered a scoreboard object to be our Receiver class but ultimately decided to have a team class fulfill that role. This allows for just three Command classes. Our Application would have two instances of the team Receiver class and of each of the Command classes as there would be a set of them for each team. Let’s call the team Receiver class, BasketballScoreboardTeam.
I thought a scoreboard object was necessary to actually keep track of the score. So we’ll create a BasketballScoreboard class. Let’s overachieve a bit and add a bonus Observer Pattern to the mix. The BasketballScoreboardTeam will know its own score. I thought the Observer Pattern would be a good approach for the BasketballScoreboard to get the score whenever a team’s score changes. So BasketballScoreboard will be an observer of the BasketballScoreboardTeam instances by implementing BasketballScoreboardTeamObserver interface. The BasketballScoreboardTeam would implement the BasketballScoreboardTeamSubject interface in order to notify registered observers when the score changes. Below is our class diagram.
Example written in C++
Now that you have had a chance to read through the descriptions and had a look at the class diagrams, let’s have a look some of the code, shall we?
Command.h
We see here that Command.h an interface with our two methods Execute() and Undo() that our ConcreteCommands will implement. Below is one of our Command derivations, FreeThrowCommand. The others are very similar so I won’t show those in this post but I will make the code available.
FreeThrowCommand.h
FreeThrowCommand.cpp
You can see that it inherits from our Command interface and has a pointer to our Receiver object, BasketballScoreboardTeam. In the source file you can see that Command interface methods Execute() and Undo() are implemented and each delegates the specific behavior to the Receiver object.
Now let’s take a look at our Receiver implementation, BasketballScoreboardTeam.
BasketballScoreboardTeam.h
BasketballScoreboardTeam.cpp
You can see there are methods that implement some scoring behaviors (FreeThrowMade(), WaiveOffFreeThrow(), etc.). Which scoring behaviors are executed are determined by the derived Command objects. Additionally, the Subject of the Observer pattern is implemented by BasketballScoreboardTeam, where Subscribe(), Unsubscribe() and Notify() are the Subject’s methods. Now we will take a look at the Observer of the BasketballScoreboardTeam, the BasketballScoreboard.
BasketballScoreboard.h
BasketballScoreboard.cpp
You can see in its constructor that the BasketballScorebaord subscribes itself as an observer to each of the BasketballScoreboardTeam instances. Upon receiving a TeamUpdate() from the Subject, DisplayScore() is called. Let’s now have a look at our Invoker of the Command Pattern, BasketballScoreboardControl.
BasketballScoreboardControl.h
BasketballScoreboardControl.cpp
This class is responsible for invoking the correct Command based on the “button” pressed from the “controller.” Since there is an undo button, this class also keeps track of the Command history and delegates the undo operation to the appropriate Command object. Lastly, we have the test that makes use of all these objects to demonstrate that our implementation works.
Output from this test is…
Basketball Scoreboard
Home Team : free throw made _______________| Score : Away Team 0, Home Team 1
Home Team : 2 point field goal made _______| Score : Away Team 0, Home Team 3
Home Team : 3 point field goal made _______| Score : Away Team 0, Home Team 6
Home Team : 3 point field goal waived off _| Score : Away Team 0, Home Team 3
Home Team : 2 point field goal waived off _| Score : Away Team 0, Home Team 1
Home Team : free throw waived off _________| Score : Away Team 0, Home Team 0
Away Team : free throw made _______________| Score : Away Team 1, Home Team 0
Away Team : 2 point field goal made _______| Score : Away Team 3, Home Team 0
Away Team : 3 point field goal made _______| Score : Away Team 6, Home Team 0
Away Team : 3 point field goal waived off _| Score : Away Team 3, Home Team 0
Away Team : 2 point field goal waived off _| Score : Away Team 1, Home Team 0
Away Team : free throw waived off _________| Score : Away Team 0, Home Team 0
Benefits of the Command Pattern
So we have seen the pattern in action. Now what are the benefits?
There are a few benefits with using the Command Pattern.
First, the Command object serves to decouple the Invoker object from the Receiver object. So if you were to replace your Receiver object with different implementation of the operation the Invoker requested, the Invoker would not be affected. You could decide to even create a new ConcreteCommand to request the operation of the new Receiver. This approach would be more in line with the Open/Closed Principle.
Another benefit is that it is easily extendable. The common Command interface is the reason. You can create a wide variety of Command implementations.
A third benefit is that it promotes low maintenance. You can easily add any number of commands without having to change any existing classes.
Finally, you can actually implement the Command interface with a MacroCommand that basically executes a sequence of Commands if there is a need. Consider our BasketballScoreboard example. We could make use of a MacroCommand by pairing a TwoPointFieldGoalCommand with a FreeThrowCommand in the case a shooter being fouled on a made two point field goal. Same could be done with the ThreePointFieldGoalCommand and FreeThrowCommand.
Recommended Resources
Here are some resources I recommend for more information on the Command Pattern
Head First Design Patterns: A Brain-Friendly Guide
Design Patterns: Elements of Reusable Object-Oriented Software
In Closing
There you have it. If you followed along, I hope you now have a better understanding of the Command Pattern. Please feel free to leave comments and feedback. Much appreciated!