Saturday, 24 August 2013

Refactor an MVC app to use the Command pattern

Refactor an MVC app to use the Command pattern

I have an MVC based application that I need to refactor to add support for
multiple levels of undo/redo. I have settled on the Command Pattern to
provide this functionality.
The application in question has functionality that adds/removes items
to/from a model. The controller provides these via methods like add_item,
remove_item etc. The implementation in the model provides the actual
implementation of the stack.
This functionality now needs to go into commands like, an AddItemCommand,
seen below.
class AddItemCommand
def execute(event)
self.item = event.item
model.add(self.item)
end
def unexecute()
model.remove(self.item)
end
end
Here an event object is provided to the command on execute, which contains
the item to be added to the model. In unexecute this item is removed from
the model. I'm glossing of over some details that aren't relevant to the
question.
What is a good way to get access to said model object from inside the
command instance?
Previously the model object was an instance present on the Controller so
the add_item method could just use self.model.add_item. But now it needs a
way to get to this model.
The model isn't a singleton but it is singular in that, there aren't
multiple instance of it. The items are added to the same instance. Should
I get a reference to a singleton of the model in the command's
execute/unexecute methods?
The textbook implementations I have seen suggest passing in the model to
the command's constructor when creating it like so,
def initialize(model)
self.model = model
end
// at instatiation
cmd = new AddItemCommand(model)
commands.add(cmd)
The drawback I see with is that I need the ability to add the command
lazily. ie:- The command is only added and executed when a corresponding
event is fired. I can maintain a mapping of events to commands to make
this happen. But I lose this flexibility when the command needs to
constructed with the model upfront.
What would be a good way to achieve flexibility to allow commands to get
at the model(s) without loosing the ability to add them lazily?
Thanks.

No comments:

Post a Comment