Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later. Also known as Token.
Sometimes it's necessary to record the internal state of an object. This is required when implementing checkpoints and undo mechanisms that let users back out of tentative operations or recover from errors. You must save state information somewhere so that you can restore objects to their previous states. But objects normally encapsulate some or all of their state, making it inaccessible to other objects and impossible to save externally. Exposing this state would violate encapsulation, which can compromise the application's reliability and extensibility.
Consider for example a graphical editor that supports connectivity between objects. A user can connect two rectangles with a line, and the rectangles stay connected when the user moves either of them. The editor ensures that the line stretches to maintain the connection.
A well-known way to maintain connectivity relationships between objects is with a constraint-solving system. We can encapsulate this functionality in a ConstraintSolver object. ConstraintSolver records connections as they are made and generates mathematical equations that describe them. It solves these equations whenever the user makes a connection or otherwise modifies the diagram. ConstraintSolver uses the results of its calculations to rearrange the graphics so that they maintain the proper connections.
Supporting undo in this application isn't as easy as it may seem. An obvious way to undo a move operation is to store the original distance moved and move the object back an equivalent distance. However, this does not guarantee all objects will appear where they did before. Suppose there is some slack in the connection. In that case, simply moving the rectangle back to its original location won't necessarily achieve the desired effect.
In general, the ConstraintSolver's public interface might be insufficient to allow precise reversal of its effects on other objects. The undo mechanism must work more closely with ConstraintSolver to reestablish previous state, but we should also avoid exposing the ConstraintSolver's internals to the undo mechanism.
We can solve this problem with the Memento pattern. A memento is an object that stores a snapshot of the internal state of another object—the memento's originator. The undo mechanism will request a memento from the originator when it needs to checkpoint the originator's state. The originator initializes the memento with information that characterizes its current state. Only the originator can store and retrieve information from the memento—the memento is "opaque" to other objects.
In the graphical editor example just discussed, the ConstraintSolver can act as an originator. The following sequence of events characterizes the undo process:
This arrangement lets the ConstraintSolver entrust other objects with the information it needs to revert to a previous state without exposing its internal structure and representations.We will transform the top-level relations into a set of corresponding domain definitions:
The next step is to translate the domain definitions into a number of Elisa components. In addition, we will use skeletons of definitions as shown in the preceding domain relationships
Based on the domain definitions a set of related components are derived. The first component implements a skeleton of the Originator domain.
CreateOriginator () -> Originator;
SetMemento(Originator, Memento) -> nothing;
CreateMemento(Originator) -> nothing;
. . .
<<implementations of >>
CreateOriginator( ) = Originator:[ ... state ...];
SetMemento(Originator, Memento) = ...;
CreateMemento(Originator) = ...;
. . .
end component Originators;
The following component is a skeleton example of a Memento component:
CreateMemento( ) -> Memento;
GetState(Memento) -> nothing;
SetState(Memento) -> nothing;
. . .
<<implementations of >>
SetState(Memento) = [ ... memento.state...];
. . .
end component Mementos;
This page was last modified on 04-12-2012 11:49:56