The command behavioral pattern allows you to represent an action that you want to perform as an object that can be copied from place to place and performed at a later time if you want.
You start by creating an abstract class called Command with a method called execute. It will help if you give the execute method a parameter so that it’ll know what the target of the command should be. You can also declare a method called undo which will allow you to implement a full-featured undo/redo system in your application.
Then you declare concrete classes that derive from the Command class that implement the execute method. The episode explains how to implement a command to cause a character in a game to move forward.
Now that you have this, you can refer to the command class anywhere in your code that you need to perform some action. This could be a user-initiated action such as pressing a key or maybe an automated action that’s performed on a schedule. You can also pass command objects around in your code. Maybe you have some code that detects what keys are being pressed. This code could first use the command pattern to map commands to different keys. Once it finds the correct Command object, it can pass that Command to other code that’s aware of the target. This decouples the command from the mechanism or button used to trigger the command and from the target.
Now code can use the moveForwardCommand class object to move any character in the game forward.
Listen to the full episode or you can also read the full transcript below.
The basic description says that this pattern lets you turn requests into objects that you can then provide to other code to run without knowing what is actually happening, that you can add to a list of actions to be performed, and that you can log to record what happened. It also mentions undoing actions.
This is a design pattern that is extremely useful if you understand it. If you don’t understand it, it’s just as easy to ignore.
Let’s follow our adventurous hero as the player guides the hero along a wilderness path. One very simple command is to move forward.
Now you could write code to move the hero forward when an arrow key is pressed on the keyboard. But what if you also have a controller with thumb pads? Do you duplicate this code in both locations? What if you allow the user to control the hero with a mouse? All these places need to be able to move the hero forward.
And we haven’t even begun to think about how we would handle an advanced feature that allows players to map buttons of their choosing to various commands.
It’s obvious that we need something that represents the idea of moving forward. But it’s not so obvious what this should be.
Before we get too far, I’d just like to point out that this pattern applies to almost any command or action that a user can initiate in your application. From opening documents, saving work done so far, starting over, or changing a preference setting. Anything you can imagine going into a menu bar or any action that user can initiate through the keyboard. Even actions that might run on a schedule automatically. These are all excellent candidates for the command pattern.
So let’s say that we have some button X that when pressed will cause the hero to move forward. Somewhere there will be code that detects if the X button is pressed. Instead of that code calling some function like moveHeroForward what we instead do is first create an abstract base class or an interface called Command that has a virtual method called execute.
Then we can have a concrete class called moveForwardCommand that inherits from the Command class and implements the execute method. I’ll get to this part in just a moment.
The next step is to declare pointers or references to various Command instances and name each of these after each of the buttons. The buttons themselves aren’t swapped or remapped. It’s what happens when the buttons are pressed that the user might want to change. Now when that code runs to detect if a button is pressed finds the X button is pressed, it just goes to the object referenced by the buttonX data member and calls the execute method.
What actually gets executed depends on what concrete class this data member references. Not only does this allow commands to be mapped to buttons but those same commands can be referenced from menu options, from mouse movements, or from finger gestures on a touch screen. This gives you some serious flexibility already. When you setup the object that handles button presses, you can assign specific concrete Command objects to each of the data member references.
We’re all familiar with a computer keyboard and all the letter and number keys and even the special keys like enter and control. But what about those function keys? You might have 12 function keys that do things like adjust volume or turn on or off wifi. The command to raise volume can follow this pattern so that 1, the code doesn’t have to be duplicated, and 2, it can be made available from different buttons or menu items.
There’s a lot more that this pattern can do. I’ve just started to explain its potential. There will be more right after this message from our sponsor.
( Message from Sponsor )
Earlier, I said that I’d get back to how the command to move the hero forward actually works. So let’s think about this for a moment. Moving the hero forward at first seems fairly easy. First get the current position and direction that the hero is facing. Then add some reasonable amount to the coordinates and call some method to change the hero’s position to the new coordinates.
The first problem that comes to mind is how will the moveForwardCommand object find the hero? All it knows is that some button somewhere or some menu item wants the hero to move forward.
Maybe you could make the hero a Singleton so it’s available anywhere. Listen to episode 60 for a description of the Singleton pattern. You want to be careful with the Singleton pattern though. It’s tempting to use it here. If we avoid that temptation though, we get some extra benefits. Right now, we have code that detects button presses calling an execute method on a Command object.
This seems like it could be trying to do too much and causing problems. If we instead make the code that detects button presses do that one thing and make sure it does it well, then not only is it easier to test but instead of calling execute itself, it can just return the command object to some other code.
Now we’ve got code at a higher level that is aware of who the hero is and wants to know if the user is trying to issue any commands. So this code calls the button detection code and gets back a Command object. If no button is pressed, then maybe it gets a null pointer or a Command that does nothing. The point is that the command hasn’t actually been executed yet. The button detection code figures out if there are any buttons pressed and manages the mapping of the buttons to a Command object which it then lets some other code figure out what to do with.
This is getting to the real power of this pattern. We’ve just turned the concept of a command into an object that can be passed around and executed at the correct location or time. What does this do for the move forward scenario?
Well, the code that asked for a command knows who the hero is and all we need to do then is modify the execute method to require a character. Did you catch what just happened?
We not only decoupled the command from the button but at the same time decoupled the command from the target of the command. Now code can use this command for any character in the game. All the extra background characters probably need to move around too, right? Not just the hero.
The moveForwardCommand now represents an abstract notion of moving forward. Exactly what it should do. It can be reused for different targets. It can be reused for different input mechanisms such as buttons and menus. And it can be mapped to different buttons if the user is left-handed for example.
And the really cool part about this pattern is we’re not even close to being done.
When a command is executed, it could if you want to remember what it did. Then you can make a copy of this command and put it somewhere such as a list of recently executed commands. Or you could write the commands to a log file. Maybe there’s a bug in your code. Well, a log file with the exact sequence of steps that were played would be a huge benefit to the development team to help figure out what went wrong.
But here’s another idea. If a command can be executed and it knows exactly what changed because of the command, then it can be undone too. Just make the command remember what changed and then provide another method called undo or something like that. And remember that list of recently executed commands? Well, now if you go backwards through that list and call the undo method, you just implemented a very useful undo feature in your application. Trying to implement a general purpose undo feature without using the command pattern would be insane.