Introduction

In software development, we often need to save an object's state and restore it later—for example, to build an "Undo" button. However, doing this manually often forces you to expose private data, which ruins your code's encapsulation. The Memento Design Pattern solves this by letting you capture and restore a private state without exposing the object's internal secrets.

In this article, we will explore the Memento Pattern to understand how it captures an object's state, when to use it, how its structure works, and how to implement a real-world Undo functionality in C#.

What Is the Memento Pattern?

The Memento Pattern is a behavioral design pattern that lets you take a "snapshot" of an object’s current state so you can restore it later.

The key benefit is that it does this without exposing the object's internal details. In simple terms, it allows you to hit "Save" on an object's state today and "Undo" back to that exact moment tomorrow, all while keeping the object's private data hidden from the rest of your code.

A Real-Life Example:

Very Simple : The Text Editor

Think about how a standard Text Editor works:

To make this happen, the editor must "remember" every previous state. However, it needs to do this without letting the "Undo" system mess with the internal logic of how the text is actually stored. The Memento Pattern acts as that hidden memory, allowing you to jump back in time whenever a mistake happens.

Structure of the Memento Pattern

The Memento Pattern relies on three specific roles to manage snapshots efficiently:

Practical Example: Simple Text Editor with Undo

Here is the step-by-step C# implementation of the Memento Pattern, broken down into its three core roles:

Step 1: The Snapshot (Memento)

First, we create a simple class to hold the data. We make the state read-only so that once a snapshot is taken, it cannot be accidentally changed.

public class TextMemento
{
    public string Content { get; }
    public TextMemento(string content) => Content = content;
}

Step 2: The Main Object (Originator)

The TextEditor is the "brain" of the operation. It is responsible for creating its own snapshots and restoring its state from a previously saved Memento.

public class TextEditor
{
    public string Content { get; set; }

    // Creates a new snapshot of the current text
    public TextMemento Save() => new TextMemento(Content);

    // Restores the text from a previous snapshot
    public void Restore(TextMemento memento) => Content = memento.Content;
}

Step 3: The History Manager (Caretaker)

The History class keeps track of all our snapshots. We use a Stack here because "Undo" always restores the most recent change first (Last-In, First-Out).

public class History
{
    private readonly Stack<TextMemento> _snapshots = new();

    public void Push(TextMemento memento) => _snapshots.Push(memento);
    public TextMemento Pop() => _snapshots.Pop();
}

Step 4: Putting It Together

Now we can see the "Undo" functionality in action. Notice how the Program doesn't need to know how the text is stored; it just tells the history to save or restore.

var editor = new TextEditor();
var history = new History();

// Type something and save it
editor.Content = "Version 1";
history.Push(editor.Save());

// Type something else and save it
editor.Content = "Version 2";
history.Push(editor.Save());

editor.Content = "Version 3 (Current)";
Console.WriteLine($"Current: {editor.Content}");

// Perform an Undo
editor.Restore(history.Pop());
Console.WriteLine($"After Undo: {editor.Content}");

Output

Current: Version 3
After Undo: Version 2

By using this pattern, you’ve built a robust Undo system that respects encapsulation. The History class manages the list of changes, while theTextEditor manages its own internal data.

What Just Happened?

Here is a breakdown of how the pattern functioned in the example:

When Should You Use the Memento Pattern?

You should reach for the Memento Pattern in these specific scenarios:

Why Use the Memento Pattern?

Real-World Usage in .NET

You will find the Memento Pattern powering features in many professional applications:

Conclusion

In this article, we have seen how the Memento Design Pattern allows you to capture and restore an object’s state safely and cleanly. We explored how it provides a structured way to implement undo/redo functionality while ensuring that your object’s internal data remains private and protected.

Hope this helps!