Memento Pattern: Preserving Application State

Ildeberto Vasconcelos
3 min readJan 5, 2024

Memento Pattern is a behavioral design pattern that aims to capture and store the internal state of an object. It allows you to save the state of an object at a specific point in time and restore it later if needed, maintaining data coherence.

It’s like taking a snapshot of the state of something you want to remember later. Imagine you’re drawing and you want to recall how the drawing looked at a certain point. So, you take a ‘photo’ of that drawing. Later, if you want to go back exactly to that point in the drawing, you can look at that photo and recreate what was there at that moment.

It’s like having a ‘go back’ button to a previous state of something, like when you’re playing a video game and want to return to the point where you were before doing something you no longer want.

The great thing is that this ‘photo’ or ‘record’ doesn’t spoil ANYTHING or interfere with what’s happening at that moment

Components

The basic structure of the Memento pattern consists of three main components:

Originator: It’s the object whose state needs to be preserved. It creates a Memento containing a copy of its internal state or can restore its state from a Memento.

Memento: It’s the class that represents the state of the Originator at a specific moment. It can contain information about the Originator’s previous state.

Caretaker: It’s responsible for storing and managing the Mementos, though without modifying their content. It can store, retrieve, or discard Mementos.

When to use it?

The Memento pattern is useful when you need to save and retrieve the state of objects without compromising their internal structure, especially in situations where preserving the history of states is crucial. It can be applied in text editors to perform “undo” and “redo” operations, in media playback applications to control progress, or in games to save the game state at different moments. It can also restore elements of a list in case of unintentional removal or regret, and so on.

Implementing with Flutter/Dart

// Memento Class
class TaskMemento {
final String task;

TaskMemento(this.task);
}
// Originator Class
class TaskList {
List<String> tasks = [];

TaskMemento createBackup() {
return TaskMemento(tasks.last);
}

void restore(TaskMemento memento) {
tasks.add(memento.task);
}

void addTask(String task) {
tasks.add(task);
}

void removeLastTask() {
if (tasks.isNotEmpty) {
tasks.removeLast();
}
}
}
// Caretaker Class
class TaskHistory {
final List<TaskMemento> history = [];

void addMemento(TaskMemento memento) {
history.add(memento);
}

TaskMemento getMemento() {
if (history.isNotEmpty) {
final lastIndex = history.length - 1;
final lastMemento = history[lastIndex];
history.removeLast();
return lastMemento;
}
return null;
}
}

void main() {
final taskList = TaskList();
final history = TaskHistory();

taskList.addTask('Buy milk'); // Adding a task
taskList.addTask('Study Flutter'); // Adding another task
print('Current tasks: ${taskList.tasks}');

taskList.removeLastTask(); // Removing the last task
final removedTask = taskList.createBackup(); // Saving the removed task
history.addMemento(removedTask); // Storing in history

print('Tasks after removing the last one: ${taskList.tasks}');

// Simulating undoing the task removal
final restoredTask = history.getMemento(); // Retrieving the removed task
if (restoredTask != null) {
taskList.restore(restoredTask); // Restoring the task
}

print('Tasks after undo: ${taskList.tasks}');
}

So when you want to give your users the ability to ‘Undo’ an action, remember the Memento Pattern.

--

--

Ildeberto Vasconcelos

📱Flutter & Dart | .NET C# 🚀💻 Turning ideas into powerful applications.💡🔥 #Flutter | .NET