Mementos

AFW 3.0 customizers must implement execute() and undo() for each type of command. This can be a lot of work if there are many types of commands. If models are small, or if the amount of data encapsulated by the model that can't be re-calculated is small, then it may make sense to simply push the model's data onto the undo stack before each command is executed. Then, the undo operation simply restores the data into the model. Much of this work can be done in the framework. But there is a problem: how does the framework know what type of data is encapsulated by the model? The framework could simply make a copy of the entire model, but then all of the data is being saved, not just the non re-computable data. The Memento pattern solves this problem:

Memento [Go4]

Other Names

Token

Problem

The command processor pattern assumes commands know how to undo themselves. Using this pattern in a framework can mean a lot of work for customizers who must provide implementations of undo() in each of their concrete command classes. Alternatively, the framework's command processor or command base class could simply save the non re-computable state of the model before each command is executed. If the command is undone, then the former state of the model can easily be restored. Unfortunately, the internal state of a model is usually private. Allowing the framework to access this data would violate encapsulation.

Solution

A memento is an object created by a model that encapsulates some or all of its internal state at a given moment in time. The memento can be stored inside of a command or command processor without allowing access to its encapsulated data. The object that stores the memento is called a caretaker. The undo() function simply passes the memento back to the model, where the encapsulated data is extracted and used to restore the model's state to what it was at the time the memento was created.

Static Structure

When a command is executed, it first asks its model to make a memento encapsulating its state information. Although the command has no idea what's inside the memento, it keeps the memento until the command is undone: