So in previous article I showed some examples of the command pattern, now I will detail a simple application.
Firstly let’s create a simple bit of HTML to help us visualise what we are doing.
Now - let’s build a simple Client. This client will have 1 responsibility - to update the HTML.
You can test it out right away by posting a log event.
See the client object running in a new window.
It outputs the following
- it works!
- See?
No surprises there, but it’s great to see our client works 100% as expected. This is a beautiful example of separation of concerns. If the client is broken, we can test it’s API directly to see what’s broken and how to fix it.
Now onto the reciever…
It’s very simple - all it does is increase and decrease it’s data by one.
Let’s test it…
And now you can see the reciever object can take actions and apply them to the client.
The outputs the following
- Data starts off with 1
- Increment. My data is now 2
- Decrement. My data is now 1
Great - still easy. Now let’s write the commands.
BaseCommand exposes a small number of functions, basically you can only run the command or flip the command the opposite way. You can see how the invoker will utualize it as follows…
This outputs
- Data starts off with 1
- Increment. My data is now 2
- Decrement. My data is now 1
You can see the ConcreteCommand implementation here.
Now finally - how do we get the invoker working?
It’s very simple - it’s sole responsibility is to push actions into it’s list of undoable actions, and then process the opposite when we request an undo. So now we have the 4 very distinct objects, how do we put it all together?
You can see the output of the command pattern below…
- Data starts off with 1
- Increment. My data is now 2
- Increment. My data is now 3
- Decrement. My data is now 2
- Decrement. My data is now 1
- can’t undo - no more actions
- Increment. My data is now 2
- Increment. My data is now 3
- can’t redo - no more actions
You push commands into the invoker one by one, but at any time you request the invoker to undo or redo an action. If it get’s too far it will alert you.
In this post I’ve detailed very simplistic versions of the command pattern. In future posts I will focus on how you can use it to facilitate more complex behaviour.