Memento Design Pattern
Prateek Mishra
Software Engineer at Google | ex. Microsoft, Walmart | Gold Medalist, IIIT Allahabad | XAT'24: 99.8
Memento design pattern is used to save the state of an object at any point of time and then later go back to the older state when required. This makes it very useful to support operations like undo, redo, backup and restore etc.
Problem
Let's try to understand this pattern with the help of a calculator application. Consider that you are working on a calculator and you want to support undo and redo operations in your application. There are two possible ways to implement these operations:
1. comes with certain performance challenges associated with recalculating the states everytime along with some implementation challenges with functions like modulus (%) being completely one way.
In order to save the state as in 2. we want our objects to have all their content with public access. This is a big caviet. Even then if we directly save/restore state from our Client code, any changes in the state would require changes in this code. This tightly couples the client code with the state.
Solution
Zero points for guessing. The solution for this problem is the memento pattern.
Like we saw earlier saving the state of any object from outside requires us to make the member variables public. Memento pattern gives the responsibility of saving it's state to the originator object itself. Thus, instead of other objects trying to copy this state from outside, our champ does it himself. This saved state is referred to as memento. Other objects may only interact with memento with a limitied interface and can only access metadata like creation time, size, operation name etc.
We create another class called the caretaker class. The caretaker is responsible for storing the mementos. As mentioned above the caretaker can only access limited information about the memento. When restoration is required the caretaker passes this memento to the originator class which then restores the data.
Let's now look at the implementation. This implementation makes use of nested classes, available in languages like C++, C#, Java etc. For languages where nesting classes is not possible there is another way which we'll look into some other day.
Implementation
Originator and Memento Class
Caretaker Class
Client Class
Code Explaination
We have a Calculate Class which containes the logic of the calculator. Inside this class is the nested Memento Class. Our Calculate class has the responsibility to save and restore it's own contents.
We also have a caretaker class called the HistoryStack. In our case, the HistoryStack contains a Stack of Object class and not Memento class because Memento class is a nested class and only the objects of it's super class (Calculate) can access it. All classes in Java extend the Object class. Since Object is a parent of all classes it can be used to reference any class. In place of Object we can also make Memento extend some public interface and allow HistoryStack to access some of the fields. This provides good security against external objects since they cannot even reference the memento class, let alone accessing the saved state in the memento class.
The Calculator (Client) Class is responsible for handling of bussiness logic and also the logic for saving the state or doing undo as per the bussiness logic.
This pattern allows us to safely create and restore snapshots of objects without breaking the encapsulation. I hope you liked this article. I regularly write such articles on #LLD and #GoodCodingPractices. Follow Prateek Mishra and learn something new every week.
References
To write this article I took help from the following sources: