Search code examples
oopdesign-patternsarchitecturecommand-pattern

Command Pattern Undo/Redo: Any issues with my approach?


I'm looking to implement a command pattern to support undo/redo in my application. The data is very closely tied together, so there are some downstream consequences of modifying some of my objects that I also want to be able to undo. My main concern is where I should put the code that executes the downstream commands. For example:

class:MoveObjectCommand
{
    private hierarchicalObject:internalObject;

    public MoveObjectCommand(hierarchicalObject:newObject)
    {
        internalObject = newObject;
    }

    public Execute()
    {
        internalObject.Location = someNewLocation;

        foreach(hierarchicalObject:child in internalObject.Children)
        {
            if(someNewLocation = specialPlace)
            {
                var newCommand:MoveObjectCommand = new MoveObjectCommand(child)

                CommandManager.add(newCommand);
            }
        }

    }

    public Undo()
    {
        internalObject.location = oldLocation;
    }
}

As far as I can tell, something like this would work be fine, but I can't wrap my head around where the majority of the execution code should actually go. Should the hierarchicalObject have a .changeLocation() method that adds all the subsequent commands, or should they be in the command itself like it is above? The only difference I can think of is that in the example above, the MoveObjectCommand would have to be called for subsequent changes to process, whereas the other way it could be called without needing a command and still process the same way (could have negative consequences for tracking undo/redo steps). Am I overthinking this? Where would you put it and why (obviously this example doesn't hit all angles, but any general best practices with the command pattern?).


Solution

  • sounds like you should have the changeLocation() method in the model (hierarchicalObject i presume). just store the new location and the object in the command.

    for undo/redo you will need a list or two for commands.

    sound like your hierarchicalObject may be a http://en.wikipedia.org/wiki/Composite_pattern, so have a take a look at the macro command in the gang-of-four book. also review: http://en.wikipedia.org/wiki/Command_pattern.

    Christopher Alexander says: "Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice".