The Memento Pattern: Your Code’s Personal Time Machine

Iftekhar Hossain
9 min readMar 24, 2024

--

What is the Memento Design Pattern?

The memento design pattern allows you to capture and restore the internal state of an object without exposing its implementation details. It allows you to store the object’s current state and roll it back to a previous state when necessary.

A real-world use case of the memento design pattern is the undo feature of the Text editor.

Let’s check how it works. Without using any fancy terms, I will try to explain it simply.

Example of Memento Design Pattern:

Let’s design a simple text editor. We will create a class named Editor with a single private field named content to store the text. To access and modify the content we will need two additional methods, a getter and a setter.

Imagine you’re typing content in the editor. This content gets saved in the content field. If you make a mistake or want to go back, how can you undo your writing?

One of the easiest solutions is to introduce another field variable, prevContent. We’ll also need setters and getters for it.

Whenever we edit the content in the Editor, it first saves a copy of the existing content to the variable prevContent . Then, it updates the editor’s content with the new value. This allows us to undo the previous edit by retrieving the content from prevContent and restoring it to the Editor. In this way, we can easily revert to the previous state of the content.

This is a good start. But it allows for a single undo. In real-world text editors you typically want the ability to undo multiple changes.

To solve this, we can change prevContent , from string to list of prevContents

Let’s check, how it will look in that case:

It is a much better solution! Now we can store multiple versions of the content in a list, allowing us to undo changes as needed.

But with this, another problem arises. While it allows undo functionality to multiple states, it requires a separate variable for each type of content change. For example, if we introduce a image field to store images, we’d need another list to track image history. This can become cumbersome as we add more features.

With every additional introduction of a field variable, each one requires a new variable to track its history for undo. This can quickly lead to a cluttered class with many fields, making it difficult to manage and maintain.

So how we can solve this?

Instead of adding multiple fields in this class, let’s create a dedicated class EditorState. This class will be responsible for storing the entire state of the Editor at a given time. This approach keeps the Editor class cleaner and easier to manage as new features are added.

For simplicity let's consider our Editor class has only one field, that is content. With that, our EditorState class will be as follows:

Now in the Editor class, we need to store the list of editor states. So we will have a composition relationship between these two classes.

Now we can add multiple fields without polluting the Editor class with too many variables. Whenever there is a change we just set a new EditorState and whenever we need we can restore it from that.

But this violates one important principle of Object Oriented Programming. That is the Single Responsibility Principle.

In simple words, the single responsibility principle means one class should have only one responsibility.

Imagine a restaurant where a single person is responsible for taking orders, cooking the food, serving it to the customers, collecting bills, and managing accounting.

I can't imagine it other than a complete disaster. Soon there will be chaos, the restaurant needs to be shut down.

The same thing applies to Object Oriented Programming. If a single class is responsible for doing so many tasks, then soon it will become unmaintainable.

In our case, our editor class has two responsibilities.

  1. Doing his own work. That is holding the content.
  2. Managing the state of the content.

To get rid of this situation let's introduce a new class, called History .

This History class will have a field called state. This state field is a list that holds zero or more EditorState objects. Each EditorState object captures the complete state of the editor at a specific point in time, including content, and other potential features like image or formatting.

The History class will also have two important methods:

  • push(state): This method adds a new EditorState object to the state list.
  • pop: This method retrieves the most recent EditorState object from the state list, allowing us to restore the editor to its previous state.

At this point History will have a composition relationship with the EditorState, and the Editor class itself no longer maintains individual states. To interact with History class, we need to add two new methods to the Editor class:

  1. createState(): This method will capture the current state of the editor and create a new EditorState object. It will then pass this object to the History class(using push the method we discussed earlier) to store the state.
  2. restoreState(): This method will retrieve the most recent EditorState object from the History (using pop method) and use it to restore the Editor's content and other properties to their previous state.

Now the class diagram looks like this:

Once the Editor is restored, the state object is removed from the list.

This functionality creates a dependency between the Editor class and the EditorState class since the Editor relies on the state object to restore its state.

This is how these classes collaborate.

Congratulations! We have just used the memento pattern to implement the undo mechanism in our classes.

Now let’s take a moment to understand how our custom class names align with the broader design pattern terminology used in many resources and books.

In the Memento Design Pattern, there are three key components:

Originator: This is the object whose state needs to be tracked for undo changes. In our case Editor class perfectly fits this role.

Memento: This is a separate object that stores originators' states at a specific point in time. Our EditorState class directly translates to a memento. It holds a snapshot of the editor’s state at a particular moment.

Caretaker: This class is responsible for managing the mementos. Our History class aligns with this caretaker role. It manages the collection of editor states, adding them, retrieving them and providing them back to the editor for restoration.

Now let's check the coding example. Though the design pattern is language-independent, I am going to use Java programming language. You will also find the code in my GitHub repository.

First of all our Editor it has only one field content and setter and getter method for the content.

public class Editor {
private String content;

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}

To manage the states of the Editor at different points in time, we’ll introduce a new class called EditorState.

public class EditorState {
private String content;

public EditorState(String content) {
this.content = content;
}

public String getContent() {
return content;
}
}

This EditorState class is specifically designed to capture a snapshot of the editor's content at a particular moment in time. It serves as a memento, holding the essential information needed to restore the editor’s state for undo operation.

Here is the breakdown of the components:

  • A Private Field: It has a single private field called content of type String. This field stores the actual content of the editor at the time the EditorState object is created.
  • Constructor: The public constructor EditorState(String content) allows us to crate new EditorState objects. It takes the current editor content as a string argument and assigns it to the private content field.
  • Getter Method: The public getter method getContent() provides a way for other parts of the program to access the stored content. It simply returns the value of the content field allowing retrieval of the captured editor state.

This class keeps the editor’s state management separate from the editor itself, promoting clearer code and easier implementation of undo feature.

Now back to our Editor class. To enable undo functionality we will add two new methods: crateState and restore

public class Editor {
private String content;

public EditorState createState() {
return new EditorState(content);
}

public void restore(EditorState state) {
content = state.getContent();
}
public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}

Now the last pieces of the puzzle, the History class:

import java.util.Stack;

public class History {
private Stack<EditorState> editorStates = new Stack<>();

public void push(EditorState state) {
editorStates.push(state);
}

public EditorState pop() {
return editorStates.pop();
}

}

This History class is the last component we need for undo functionality. It utilizes a Stack data structure to maintain a list of EditorState objects. These EditorState objects, as you recall represent snapshots of the editor content at different points in time.

Now let's combine all together and see the undo mechanism in action. I have created a main class that holds the main method.

public class Main {
public static void main(String[] args) {
Editor editor = new Editor();
History history = new History();

editor.setContent("a");
history.push(editor.createState());


editor.setContent("b");
history.push(editor.createState());

editor.setContent("c");
editor.restore(history.pop());


System.out.println(editor.getContent()); // prints b in the console

}
}

Here’s a step-by-step breakdown of how we use these classes together in the main method:

  1. Create the Editor and History: We begin by creating an Editor object to manage the content and a History object to track changes.
  2. Set Content, Save States: We set the initial content “a” and call editor.createState() to save a snapshot. This is pushed to the History using history.push() . We repeated this for subsequent changes “b” and “c”.
  3. Undo: To undo the last change (“c” to “b”), we simply call history.pop() . This retrieves the previous state and restores the editor's content.

Congratulations! You’ve successfully navigated the world of the Memento pattern and its implementation for undo/redo functionality.

Thank you for your patience in reading this explanation. I’ve strived to break down the concepts into clear and understandable steps.

If you’d like to explore further, consider delving into real-world applications of the Memento pattern beyond text editors. It’s a versatile design pattern used in various software development scenarios!

If you found this article helpful, please consider showing your support by following me and leaving a comment below.

For fellow freelancers, I invite you to explore my YouTube channel and connect with me on LinkedIn. I look forward to meeting you.

I specialize in Java and Spring Boot development as a freelance software developer. If you require assistance with your Spring Boot application, don’t hesitate to get in touch.

Thank you for your time. You can also find me on Fiverr and Upwork. Feel free to reach out there as well.

--

--