Commands, Interfaces, and the Undoable Command
As we developers move further and further away from just making webpages and move into full fledged RIAs, there is one specific piece of functionality that many users request, the ability to undo their last action. To a user this seems like the simplest thing, and I am sure the users believe it is some “switch” that you forgot to flip. In all actuality the “undoable” action is fairly complicated and requires a few moving parts, all of which are based around the command pattern.
The concept is pretty simple, each action that the user takes is completed on your application and it’s data as a command. The command has two methods in it’s interface execute and undo. Whenever a command is called, the application will store this command in the order they are received. When the command is called, the execute method is the one actually used. When the user wants to “undo” their last action the latest command’s undo method is called and the undo method holds the logic necessary to remove the changes caused by the execute method.
IUndoableCommand
The command pattern is probably one of the easiest design patterns to understand; the quick explanation is that the command pattern tells an object to run a method. This has been expanded on to usually include interfaces that include the execute method. I am going to use this same pattern and execute method and add one other method to my interface, the undo method. The reason I am taking the time to set up an interface is so that all the commands I build can share the same signature, so I don’t have to worry about calling the “run” method on one command and the “execute” method on a different command. Now all my commands have the same specific IUndoableCommand signature.
{
/**
* Interface for commands with an undo method.
* @author jonbcampos
*
*/
public interface IUndoableCommand
{
/**
* Executes the command.
*/
function execute():void;
/**
* Rolls back the execute method.
*/
function undo():void;
}
}
My Command
With my interface created I now put together my command. This command is simple, it adds a word to a collection. You will notice that I store references to all the objects that this command needs to run it’s execute and undo methods. The reason I do this is so this command works without me having to know what to send it. Another reason why my interface doesn’t have any arguments to the execute and undo methods.
{
import mx.collections.ArrayCollection;
/**
* Command to add a word to a list.
* @author jonbcampos
*
*/
public class AddWordCommand implements IUndoableCommand
{
/**
* Save reference to list.
*/
private var _list:ArrayCollection;
/**
* Store the object reference.
*/
private var _listObject:Object;
/**
* Constructor stores references.
* @param word string to add
* @param list collection to add word to
*
*/
public function AddWordCommand(word:String, list:ArrayCollection)
{
_listObject = new Object();
_listObject.label = word;
_list = list;
}
/**
* Adds the word to the list.
*/
public function execute():void
{
_list.addItem(_listObject);
}
/**
* Removes the word from the list.
*/
public function undo():void
{
var index:int = _list.getItemIndex(_listObject);
_list.removeItemAt(index);
}
/**
* Extraneous label for my view.
* @return
*
*/
public function get label():String
{
return "Added: "+_listObject.label;
}
}
}
Your Application
Without knowing it you have created most of the structure to undoable commands, the next thing to do is to manage your commands list. For this I have a simple collection right on my application. For a larger application I would probably set up a much more formalized list with with specific accessors, but for my example this will work. Along with my list to store commands as they are executed, I also have a pointer to the current command. This keeps the place of what command I am currently on so that I can undo and redo commands at will, creating an entire history list.
The logic in this example is:
1. When a new command is added to the command list, any commands beyond the pointer are deleted, and the pointer is set to the newest command.
2. The command list is restricted where you can’t jump between elements, like a linked list you have to go from 1 to 2 to 3, not 1 to 3.
3. Make sure to always execute the command currently being pointed at before moving to the next.
With this all in place you can now see my undoable application with history management.





Hey Jonathan!
I met you awhile ago at the BugQuash.
Your undoable command seems to work pretty well. The only thing is it doesn’t account for is a user who chooses to undo, adds a new word then wants to undo a few times after that. Basically this history doesn’t save Undos as part of it’s history.
Dan nice to hear from you. You are right that this example doesn’t account for storing the history of undo commands. I could say that it is outside of the scope of the example, but honestly I just didn’t think about it
definitely a place for an improved example.
I have to admit I know this pattern but haven’t implemented it before. I’d seen bindings for it in my favourite MVC but as I googled around to check out alternative implementations I noticed we got that interface and a manager implentation for free with the TLF! Also the flashx.operations package looks like it has some cool patterns
http://en.wikipedia.org/wiki/Memento_pattern
http://en.wikipedia.org/wiki/Finite_state_machine
I will definitely use command pattern in Flex/PureMVC applications.