Memento Design Pattern Using C#

Memento falls under the behavioral design pattern category. The purpose of memento design pattern is to record the internal state of an object. Recording of an object’s internal state can also be referred to placing checkpoint at different level of program execution. The checkpoints are later used in case of undo or any unexpected operation (e.g. crash) by the program to retrieve the state of an object. Memento should not be mistaken with command pattern. Command pattern can use mementos to maintain state for undoable operations and mementos can be used by iterators.

Problem

In order to save an object’s internal state, state must be saved somewhere. Saving an object’s internal state externally is not easy as object may or may not encapsulate all the data. Therefore, making it inaccessible to objects outside to save their state.

Solution

Memento comes to rescue by storing a snapshot of internal state of another object. The object that stores the internal state is called Memento and the object of which internal state is saved is called originator. The memento pattern also utilizes a Caretaker class. This is the object that is responsible for storing and restoring the originator's state via a Memento object.

But it is originator that initializes memento with its internal state. A memento is opaque to an originator and to its caretaker.

Example

Let’s consider a Rectangle which is drawn on a canvas. Its position is initially fixed but can be changed on canvas either by dragging or changing its x, y coordinates in the toolbar. The operation can be undone by clicking undo button. The idea is simple as explained above. We need to save the internal state of rectangle in a memento when coordinates are changed. When undo is performed, we use memento to reset rectangle; the originator. The example can be extended to perform multiple undo operations. But in my example, for the simplicity I have permitted only 1 undo operation. However, with the help of iterators, multiple undo operations can be implemented also.

As said, the Memento is opaque to other classes; the class can typically be a private inner class of the Originator. Therefore, the Originator will have access to the fields of the memento, but outside classes will not have access to these fields. This means that internal state information can be transferred between the originator and the memento within the Originator class, but outside classes do not have access to the state data stored in the Memento.

As memento is either an inner class or private class, caretaker will have only reference to memento. In other words, caretaker is a safe-keeper of a checkpoint; the memento. At later point, when needed, caretaker can use the reference and instruct the originator to reset its state with respect to memento.

Class diagram

So as to summarize, memento shields encapsulation and does not let originator expose its internal state and implementation. It also supports single responsibility principle by helping originator not to keep track of its previous state since this is the responsibility of the caretaker.

However, using the memento pattern can be expensive depending on the amount of state information that has to be stored inside the memento object. In addition, the caretaker must contain additional logic to be able to manage mementos.


Similar Articles