Design Patterns - Command Pattern
What's a lonely geek to do late in the evening? Write about the Command Pattern of course...
Let's start with the definition: "Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undo-able operations."
And now, time for the spec I just made up: Our UI has three buttons at the bottom of the screen, which contain various actions. These actions are different depending on the selected item however. We need to implement this piece of UI code, without it having any knowledge of our game units.
How would we approach this? Let's say these buttons are nothing more than placeholders, to be filled with real buttons whenever a unit is selected. Our game engine will respond to a selected event and create and pass on the real buttons to our UI code.
So, our UI code will only need to know about one thing, a button. Let's create an interface for this type of button, and coincidentally name it ICommand :)
We'll code our UI code against the ICommand, respecting to program against an interface and not an implementation. In the end, we'll need some real implementations as well however. So let's create some "buttons", which I'll call Commands from now on.
Right now we only have two types of items, GameUnits and IBuildings. Each Command will perform an action against one of these, encapsulating the object through composition.
For this example, we can make a GameUnit turn Aggressive, Normal and Suicidal. We can also power buildings on and off.
Notice these Commands themselves are written against interfaces as well, our good habits are already starting to pay off.
The NoCommand is a little tricky, it's just a dummy object, which sometimes is called a Null Object as well. It's being used for buttons which don't do anything, basically their default value.
It's time to create our UI code, the GameControls class. This class will contain the three buttons, ICommands, and helper methods to assign real buttons into the placeholder slots, as well as triggering button clicks.
Additionally, there's another requirement which has surfaced. We want to be able to undo our last action, whenever possible, can't undo suicide ;)
We'll accomplish this by storing the last ICommand, and when an undo action is needed, call the Undo() method on it, since each command provides the exact opposite of Execute() in it's Undo() method.
That's all the code that was needed to implement the Command Pattern actually. Our GameControls class has no idea GameUnit or IBuilding exists, it's totally decoupled from them. By using Command objects, we can treat them as little blocks which can be stored in a queue for multiple level undo, we can let several threads pop commands of a queue to process them in parallel, and much more.
Let's have a look at the full diagram, with the official names written on them as well.
Time to put our code into action and test it.
Let's imagine we have a full blown engine, and when a unit is selected, various events get fired, resulting in the creation of the correct ICommand objects, being passed to our GameControls UI code, which causes buttons to be displayed on screen. We'll also simulate a click on the various buttons and the undo button.
That's it! I've uploaded the solution for the Command Pattern so you can have a look at the code of the Command Objects and the details of the GameControls.
Some additional information on the Command pattern: