Memento Design Pattern ✨😎

Irushinie Muthunayake
Geek Culture
Published in
7 min readMay 26, 2021

--

An overview of the Memento Design Pattern and its implementation with a real-world scenario!

📍 According to the book “Design Patterns: Elements of Reusable Object-Oriented Software” by a gang of four, the Memento Desing Pattern belongs to the category of behavioral design patterns and, also known as snapshot pattern.

📍 The Memento is a design pattern was designed to restore an object to its previous state.

Consider the below technical examples where we use the Memento Design Pattern

🌞 You have been using the Microsoft Word to do your work and have you ever seen an undo feature there🧐 By clicking the undo option you can go to your previous states.

🌞 ·We can rollback all the calculations we did in memory with a button click in calculator applications..

🌞 In code editors which we use for editing source code of computer programs, there we can undo and redo any code change with simple commands.

🌞 javax.swing.text.JTextComponent the class provides an undo support mechanism. javax.swing.undo.UndoManager can act as a caretaker, an implementation of javax.swing.undo.UndoableEdit can act as a memento and implementation of javax.swing.text.Document can act as an originator.(Ref:https://howtodoinjava.com/design-patterns/behavioral/memento-design-pattern/)

When to Use Memento Design Pattern

⚡️ In most cases, the Memento Design Pattern will be mostly used in times where we need to undo, rollback or revert.

⚡️ We can use this pattern when we need direct access to the object’s fields/getters/setters violates its encapsulation. (Ref:https://refactoring.guru/design-patterns/memento)

Three pillars of Memento Design Pattern

The Memento design pattern uses 3 objects for its implementation. They are the Originator, the Caretaker, and the Memento.

Originator

📍 Simply we can say that this is the one we need to maintain the state. Also, this object knows the way to save and restore itself.

Caretaker

📍 Caretake is the one who keep the track of the originator. So accordingly we can say that this object knows when and why the Originator wants to save & restore itself.

Memento

📍 Memento is created, written, and read by the Originator, and guided by the Caretaker. No one can change the state of this once it is created as the memento is an immutable object.

……………………………………………………………………………………..

✨ So, when implementing, the Originator coupled with memento and pass the state to the caretaker. So whenever we need to go back to the previous state we talked to the caretaker and check the previous state and move.

For a better understanding look at the below class diagram and the sequence diagram.

Class diagram of Memento Design Pattern

Ref:https://dzone.com/articles/memento-design-pattern-in-java

Sequence diagram of Memento Design Pattern

Ref:https://javadevcentral.com/memento-design-pattern

Let’s move to a real-world example to understand the implementation of this design pattern.

💥 Scenario

There is a pizza ordering application called “Pizza Express” and there is an option to add and remove extra layers to the particular type of pizza you chose.

So here, you need to add Bell Pepper, BBQ, Chicken Ham, Capsicum, Cheese and Prawns as extra layers. And then need to remove Prawns and add a new extra layer of TandooriChicken and revert all again.

So let’s see the implementation for this scenario 🤓

Step ⓵

▪️ Let’s create the Originator class as below.

▪️ In line 9, I have created the method to add layers.

▪️ For memento, I have created an inner class inside this PizzaBasket class as shown in line 31. (But if you wish you can use a separate class for the memento)

▪️ private ArrayList<Layer> getlLayers(), Here the getLayers method (in line 38 )is declared as private which means only the PizzaBasket can access this getLayers method.

▪️ Also, there are two specific methods inside this class. They are

✨ To preserve the PizzaBasket state.- Here, we have a caretaker and we have to give the state of the PizzaBasket to the caretaker. But it's not good to return the Pizzabasket object itself, because we could not be able to change it and will not be able to add layers without affecting the previous state. Therefore here I have returned the PizzaMemento to the caretaker as shown below.

public PizzaMemento save() {
return new PizzaMemento(getLayers());}
// here, it has created a new PizzaMemento object using the current PizzaBasket.

✨ To revert the PizzaBasket state- Here the revert method is used to revert the object

public void revert(PizzaMemento pizzaMemento) {
layers = pizzaMemento.getlLayers();}

Step ⓶

▪️ Let’s implement the Caretaker class as follows.

▪️ The Caretaker is the person who keeps the state of the previous object.

▪ ️Let’s say you assign one layer and save it. Then assign another layer and save it. Again you did the same. And now if you need to rollback, you need to give the first state first. That means it is “Last In First Out”. That means we need to implement the caretaker as a Stack.

Here,

☀️ This method is used to save the pizzaBasket's state. And [pizzaBasket.save()] will return the PizzaMemento.public void save(PizzaBasket pizzaBasket) { history.push(pizzaBasket.save()); }
....................................................................
☀️ In the below method. "If - else" is used to check the current state of the PizzaBasket.public void revert(PizzaBasket pizzaBasket) {
if (!history.isEmpty()) {
pizzaBasket.revert(history.pop());
}else{
System.out.println("Cannot Undo");}}

Step ⓷

▪️ This is the Layer class and there I have declared only one variable.

Step ⓸

▪️ This is the main method.

Output:

▪️ Here as the first layer, we have got 2 layers because we save the PizzaBasket after adding 2 layers.

📍 So here what actually happens is, we created the Pizzabasket and put the entire PizzaBasket to the caretaker.

▪ ️According to the scenario now we need to remove the Prawn layer from the PizzaBusket.

▪ Now see the below code ➔

Output:

▪ So according to the output you could see that the below-highlighted part has been repeated twice.

Why did this happen?😨🥵

Here we added the layer to the PizzaBasket and gave that PizzaBusket to the caretaker. And then said to revert this. So at that time, the caretaker will give the Pizzabasket that we gave him last, which means it is the same PizzaBasket that we have in your hand now.

So we can change the code as below.

Here we added Prawn but didn't give it to the caretaker. So now what the caretaker has is the cart which has “cheese”.

So now let’s add TandooriChicken to the PizzaBusket.

Output:

So here, After reverting Tandoori chicken it comes back to the Capsicum state. But what has happened to the Cheese state? 🙄🧐

This happened because we added Prawns but we didn’t give that to the caretaker and we reverted it. That means the caretaker returned the PizzaBucket which had cheese as the last state. So now the caretaker doesn't have the PizzaBucket which has the cheese as the last state and it has the PizzaBucket which has Capsicum as the last state.

And then we added Tandoori chicken (without saving to caretaker) and reverted it again. So now the caretaker returned the Pizzabusket which has Capsicum as the last state.

Click on the below Github link to see the full source code for this scenario:

Advantages and Disadvantage of Memento Design Pattern

Advantages of Memento Design Pattern

⚡️ The most important benefit of this memento design pattern is that you always have the ability to discard the unessential changes and restore them to a stable state.

⚡️ Easy recovery techniques are provided by this pattern.

⚡️ The Memento design pattern conserves encapsulation boundaries.

Disadvantages of Memento Design Pattern

⚡️ The application will consume a huge amount of RAM if the user creates mementos many times.

⚡️ The extra time to save the states will reduce the overall performance of the application.

--

--