The Memento Pattern
The Memento Pattern
Contextual Forces
Motivation
Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later.
Encapsulation
The state of the Originator is encapsulated by the memento, as are the rules of resetting the state later.
Procedural Analog
Serializing state to a file internally within a system, and then reloading it later (on demand) is a procedural way of accomplishing what the Memento does with objects.
Non-Software Analog
A time capsule, buried for future generations to discover.
Implementation Forces
Example
Sometimes it is necessary to take a point-in-time “snapshot” of an object so that it can be temporarily changed and then later restored to the original condition. This means that the state of the object must be able to be recorded and then restored. If the state in question is encapsulated (a best practice) then this would seem to be a challenge. How can we extract that which cannot be read? How can we restore that which cannot be written? The Memento solves this problem.
The stateful object in question is typically called “the originator”. The object that captures the state is the Memento. The Memento must have a more intimate relationship to the originator than the rest of the system. There are many ways to accomplish this. In the example below, a narrow interface is used. Other implementations are possible depending on the technology being used.
Questions, concerns, credibility checks
The Memento in the example does not literally enforce encapsulation in that a client object could, theoretically, downcast the reference in the same way that the originator does. If this is a concern, then the ConcreteMemento may be made package private, or may be an inner class of the originator if the technology supports this idiom.
Options in implementation
Other possibilities exist, including the use of delegates or assembly meta data in .Net, etc.
Consequent Forces
Testing issues
The Memento is a enabler for testing in that it allows a test to take an object through various scenarios and then return it to its original condition. Testing that the Memento accurately restores the state can be accomplished by making the test the Originator, or by making it a subclass of the Originator. The latter approach requires the state to be protected rather than private.
Cost-Benefit (gain-loss)
The benefit is the ability to "undo" changes to an object's state. This requires that the Memento have access to state that is otherwise encapsulated. The Memento, however, does break encapsulation and thus a bug in a memento can effect the Originator.