Design Pattern Part 6: Memento Design Pattern

Ravindran Kugan
6 min readJun 28, 2021

--

Revert

You guys must have some experience with video games right. Video games have a save feature. While you playing the game if you think you made the wrong decision or wanted to try out something different you can simply load the old state and start from that specific point. The design pattern that I am going to talk about today also does this sort of thing. It allows us to reset our object, sounds cool right…

In this article I will be talking about the Memento Design Pattern. If you are new to Design Patterns, I would recommend you all to read my first article about Design Patterns by clicking here. Now les talk about Memento Design Pattern.

Memento Design Pattern

Memento Design Pattern falls under the behavioral type in the gang of four. Just like I told in the introduction this design pattern helps us to rewind. In technical terms it helps us to rewind an object to its previous state. Memento design pattern has 3 main pillars.

  1. Originator : The original class that we are going to take a snapshot of. This can change states depending on the user inputs.
  2. Caretaker : The class that will decide on when to rollback and go to the previous state of the object that is currently in use.
  3. Memento : These are the save points or in other words, snapshots of the object that we are going to have a backup of.

Now that we know the technical terms of the memento design pattern, lets take a look into a simple implementation to understand this better.

Scenario

Imagine a food ordering system. We can add food to our basket and while adding them we can press the undo button to remove the last added food in our basket. As I have talked about the 3 pillars of this design pattern, I have implemented the 3 classes for the food ordering system.

Implementation

As we are going to be creating a food basket. We will be storing the food objects inside them. Food class is a simple class that only contains a string to store the food name, a constructor and a toString() method as you can see below.

Now that is out of the way lets create the originator and the memento classes. I have created the memento class as an inner class of the originator class. You can create the memento class as a separate class as well if you want.

Before we go to the next section let me explain some things. Look at line number 7, I have created an ArrayList that will store a Food object directly instead of creating it as List<> = new ArrayList<>() the reason is, see the method in line 13. The method is returning will be returning the current ArrayList object foods, if you remember collection classes are reference type, so if we directly assign this into another variable and change that, the original will also be changing. To avoid that we are using the clone() method. And clone method is not supported for the base List interface. So that is why we are directly using the ArrayList class.

Note: Some of you may be asking the question why create an ArrayList object with the type of List, basically like List<> = new ArrayList<>() this. The reason is if we are to change the ArrayList into a Vector in our implementation we can simply change it without having to worry about breaking our code. If we create objects like this, the object will only be able to implement methods that are available in the base List<> interface.

Other than that I have also created the FoodBasketMemento class. In this class I have a single ArrayList variable just like the basket and have a getter and setter.

Now in the Originator as you can see we have two other important methods that we need to talk about.

=>In line 17 we have the save() method. This method will assign the current object into the memento by creating a new instance of the FoodBasketMemento (Memento Class). (We are making sure it is a new object by returning a clone in our getter as explained earlier.)

=>next we have the revertBasket() method in line 21. In this method we are assigning the state that is saved in the memento to the originator. (the memento is being passed as the parameter)Basically reverting back to the previous state.

Besides these I have two other methods, one is to add items, and the other is an overridden toString() method that will print the current state of the object.

The FoodBasketMemento class can be understood easily, it has a constructor that takes in the instance of the FoodBasket(Originator) and a getter that will return the current the Food ArrayList instance that is saved in the memento class.

Now that we have the Originator and the Memento class, we need to create the care taker class.

The care taker class will be the one that will save the backup and will revert to the previous state if needed. As you can see we have created a stack object. The reason for this is that, if are reverting to a previous state it is going to be the object that was saved last, so last in is going to be the first one out. Thus a stack is used. In this stack we are storing the memento objects.

=>If you look at the save() method we are getting the instance of FoodBasket (The originator ) as the parameter. So when we call the push method we will be calling the save() method that is inside the Originator. The save() in the originator will be returning us a memento object.

=> Then we have a revert() method. This method is fairly straight forward. If the stack is empty it will simply say that we can not revert. If there are items in the stack, it will be calling the revertBasket() method stored in our originator and will pass the last saved instance of the memento by calling the pop() method of the stack.

Now that is how our major 3 pillars look like. Lets create a main method and see how it runs.

I am creating instances of FoodBasket(Originator and Memento) and the FoodBasketCareTaker(Care taker) classes. After that I am just adding some items and then printing the FoodBasket. Then from line 26 I am reverting the FoodBasket back to the previous states. If I run the code the output is this.

//Insert Image

As you can see, the state with cold soda is printed again even though we reverted it at line 26. Now remember the reason for this is because we are not removing an item by calling the revert, we are going back to the previous state of the object. So the last saved object in the memento class is the one with cold soda, that is why we are getting that state back when we are reverting. A simple fix for this problem is to comment out line 23.

Key Points

=>This design pattern should be implemented carefully, as if one is to create a lot of instances of an object it might clog up the ram and will cause a performance hit.

=>We should also have a way to clear up older snapshots of the memento inside the caretaker.

=>The major advantage is we are creating backups without violating the encapsulation.(No public keywords for our objects)

Thanks for reading my article 😀

REFERENCES

Click here to go to my GitHub repo for the above used code.

The following are the links to my previous design pattern articles.

Part 1 : Overview of Design Patterns and Singleton Design Pattern.

Part 2 : Factory Design Pattern

Part 3 : Prototype Design Pattern

Part 4 : Builder Design Pattern

Part 5 : Chain of Responsibility Design Pattern

These are the references that I used to write this article.

--

--