Listen to this post
Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later. (GoF)
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 (which is 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.
Qualities and principles
The Memento allows us to preserve the encapsulation of state, even under circumstances that would seem to dictate breaking it. The Memento object is strongly cohesive in that it only stores state, nothing else. The interface of the originator is derived from the client’s need to take a snapshot of the state. The ConcereteMemento (in the example) can be substituted for the Memento that the client is exposed to, allowing the interface to vary in a way that is hidden.
The Memento is an 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.
Questions and concerns
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. There are other approaches, as described in the Pattern Repository.