The power and simplicity of the Command pattern

Never thought of how to implement an "undo" function? Not that easy, huh? People in our architecture class today came up with quite creative solutions: two separate stacks storing operations, versioning of the object to go back etc... All quite complex. Well, I've thought about that already about a year ago, so it was quite easy for me and there you actually see how simple such a task becomes if you know the right pattern (I'll come to it immediately).

The key is actually to encapsulate the operation and the object the operation acts on. If you encapsulate that within an object you're already pretty much done. Every time you perform an operation you create such an object encapsulating that operation.



If you knew about it already...yes, it's the Command pattern :) . Now the interface above is the standard implementation, but adding undo is not a major difficulty. You can either add the method to the ICommand interface or create another abstract class/interface UndoableCommand using ICommand. Take for instance the operation "make bold" of a word within a document. Applying the Command pattern and adapting it for undo and redo functions is quite simple



For each concrete command you implement the interface. So an example implementation of such a BoldCommand could look like
public class BoldCommand implements ICommand{
private Word aWord;

public BoldCommand(Word aWord){
this.aWord = aWord;
}

public void execute(){
//call some appropriate object that knows how to perform
//the action, i.e.
aWord.setBold(true);
}

public void undo(){
//undoing is easy since we know here what we did previously and
//we have the reference to the object we acted upon
aWord.setBold(false);
}

public void redo(){
execute();
}
}
I guess this should look now pretty obvious to you. Of course this is just a simple code for demonstrating the idea. You need some more sophisticated structures that take care of these command objects. For the undo/redo you'd probably have some list that tracks all of these objects, removes old ones etc...
If you programmed already for the Eclipse platform, you probably came across the IAction interface and Action classes. Well that's one implementation of such a command pattern. They use it quite heavily there.

Now that you know the pattern, think about the solution you came up with previously (2 stacks, operations, undo operations etc..). Quite complicated :) I like this example because I think this example of the undo/redo functionality explains quite clearly the improvement of your code if you know the right - and obviously suitable - pattern.
Kindle

Comments

0

Your ad here?