Memento Pattern in C# - Undo & Redo

Written by devleader | Published 2024/02/05
Tech Story Tags: design-patterns | memento-pattern | dotnet | csharp | software-design-patterns | memento-pattern-in-csharp | implementing-memento-pattern | csharp-tutorial

TLDRUnlock the potential of the Memento Pattern in C# for seamless state restoration in your software projects. This comprehensive guide covers the origin, principles, and step-by-step implementation of the Memento Pattern with detailed code examples. Learn to create Originator, Memento, and Caretaker classes and effortlessly add 'Undo' functionality to your application. Understand the benefits and tradeoffs of this pattern, and enhance your C# coding skills.via the TL;DR App

The Memento Pattern is a software design pattern that is used to save and restore objects to their original states. The purpose of the Memento Pattern is to enable effortless restoration of an object’s previous state. In this article, we’ll be looking at the Memento Pattern in C# with code examples.

In software engineering, state restoration is the ability to bring back the previous states of an object or system. This is important because it helps prevent system crashes and loss of data. With the Memento Pattern in C#, developers can implement state restoration without much effort. This design pattern is particularly useful when building applications that need to track changes to an object over time.

By following the steps outlined in this article, C# developers can easily implement the Memento Pattern in their C# projects.


This article includes an affiliate link to Amazon. You won’t be charged anything extra for clicking on these links, but you will be supporting me if you do choose to purchase something through one of these links. Thanks!

How the Memento Pattern Works

The Memento Pattern is a software design pattern that allows developers to restore an object’s previous state with ease. It is often used in undo-redo systems or situations requiring state restoration — and we’re all familiar with pressing ctrl+Z to get our work back! It works by separating an object’s state and creating a memento object that stores the state. This memento object can later be returned to restore the object’s previous state.

Origin and Principle of the Memento Pattern

Design patterns are generally classified into three categories: behavioral, creational, and structural patterns. The Memento Pattern falls under the behavioral pattern category. It was first introduced by the GoF (Gang of Four) in their book “Design Patterns: Elements of Reusable Object-Oriented Software”.

The principle of the Memento Pattern is to save and restore an object’s previous state without exposing its private implementation. This pattern ensures encapsulation and separation of concerns by separating an object’s state from the object itself. This way, the object’s state can be retrieved and restored without compromising its integrity.

Different Components of the Memento Pattern in C#

The primary components of the Memento Pattern in C# include the Memento, Originator, Details, and Caretaker. The Memento object stores the object’s state, while the Originator creates and restores the object’s state. Details provide a snapshot of the object state, and Caretaker is responsible for the object’s history.

The Memento object captures and saves the current state of the Originator object. The Originator object creates a new Memento object and saves its state in the Memento object. The Details object is used to provide a snapshot of the object state. Caretaker is responsible for saving and restoring the object’s state history. We’ll see this in more detail by looking at some code momentarily!


Examples of the Memento Pattern

One use case example for the Memento Pattern is for a game that allows the save and load of levels. A game level can be designed as an object, and its state, including objects placed, scores gained, and player location, can be captured and saved in a Memento object. The system can later load and restore the saved level state.

Another example of where the Memento Pattern can be applied is in a text editor system (just like the code editor you use daily). In such a system, users can perform undo and redo operations after typing. The Memento Pattern can be used to store a snapshot of the text area’s state. When an undo operation is performed, the text area can be restored to its previous state, as stored in the memento.

Get your copy of the Design Patterns E-Book now! All future revisions and additions are TOTALLY FREE.


Steps to Implement Memento Pattern in C#

Creating the Originator Class

The first step is to create the Originator class, which is responsible for creating and restoring an object’s state. The Originator class needs to have a method that returns a Memento object containing the current state of the object.

To create an Originator class, you’ll first need to define the state you want to save as properties. Then, you’ll need to create a method that returns a new Memento object with the current state. This method should save the current state of the properties in a new Memento object.

Below is an example of a simple Originator class that saves and restores a string property:

public class TextEditor
{
    private string text;

    public string Text
    {
        get => text;
        set
        {
            text = value;
            Save();
        }
    }

    private void Save()
    {
        Console.WriteLine($"Saving state: {text}");
    }

    public TextEditorMemento CreateMemento() => new TextEditorMemento(text);

    public void Restore(TextEditorMemento memento)
    {
        text = memento.Text;
        Console.WriteLine($"State restored: {text}");
    }

    public class TextEditorMemento
    {
        public string Text { get; private set; }

        public TextEditorMemento(string text)
        {
            Text = text;
        }
    }
}

The Memento Class

The next step in implementing the Memento Pattern is creating a Memento class. The Memento class stores the state of the Originator object and provides access to that state when the object’s state needs to be restored.

To create a Memento class, you’ll need to define the state you want to save as properties. Then, you’ll need to create a constructor that takes in the object’s current state and sets the state properties.

Below is an example of a simple Memento class for our TextEditor:

public class TextEditorMemento
{
    public string Text { get; private set; }

    public TextEditorMemento(string text)
    {
        Text = text;
    }
}

The Caretaker Class

The third step in implementing the Memento Pattern is creating the Caretaker class. The Caretaker class is responsible for storing and managing the Memento objects that hold the Originator object’s state. It provides an interface for saving and restoring the object state.

To create a Caretaker class, you’ll need to define a list for storing the Memento objects. Then, you’ll need to create methods for adding Mementos to the list and retrieving Mementos from the list.

Here’s a simple Caretaker class for our TextEditor example:

public class TextEditorHistory
{
    private readonly List<TextEditorMemento> _mementos = new List<TextEditorMemento>();

    public void Save(TextEditorMemento memento)
    {
        _mementos.Add(memento);
        Console.WriteLine($"Editor state saved: {memento.Text}");
    }

    public TextEditorMemento Undo()
    {
        var memento = _mementos.LastOrDefault();
        if (memento != null)
        {
            _mementos.Remove(memento);
            Console.WriteLine($"Editor state restored: {memento.Text}");
        }

        return memento;
    }
}

Adding Undo Functionality

The final step is to add ‘Undo’ functionality. When ‘Undo’ is performed, the latest Memento object is retrieved from the Caretaker object and used to restore the object’s state. The Originator object is updated with the restored state.

To add ‘Undo’ functionality, you’ll need to modify the Originator class to include a method that restores the object’s state from a Memento object. Then, you’ll need to modify the Caretaker class to keep track of a history of Mementos so that the application can undo changes.

Here’s an example of a simple ‘Undo’ implementation for our TextEditor example:

var textEditor = new TextEditor();
var history = new TextEditorHistory();

textEditor.Text = "hello";
history.Save(textEditor.CreateMemento());

textEditor.Text = "world";
history.Save(textEditor.CreateMemento());

textEditor.Restore(history.Undo()); // Restores state to "hello"

Benefits and Tradeoffs

Benefits of the Memento Pattern in C#

Implementing the Memento Pattern in C# can bring several benefits to your code. First, it can simplify the application’s state restoration process. The Memento Pattern allows objects to be restored to their previous state with minimal complexity or interference. It can also improve an application’s scalability and flexibility since it separates an object’s state and its implementation.

Another benefit is that it can improve the code’s readability and maintainability by organizing the necessary code into separate components. The Memento Pattern meets the ‘Single Responsibility Principle’ and encapsulates all of the necessary information regarding the object’s state. Compared to some other design patterns, the Memento Pattern is more maintainable, scalable, and flexible.

Drawbacks of the Memento Pattern in C#

Like any other software design pattern, the Memento Pattern has drawbacks. Implementing the pattern requires an increase in memory since the Memento objects use more memory to store states. This increase can pile up, resulting in performance degradation — So you need to be careful when managing state. It might be a good opportunity for some tests!

In addition, the Memento Pattern can overcomplicate simple applications. When deciding whether to use the Memento Pattern or another software design pattern, it is essential to consider the application’s use case. The Memento Pattern is most useful when an object or application undergoes frequent state changes. The pattern would not be recommended for systems with minimal state changes.

In general, the Memento Pattern is an excellent software design pattern that can bring valuable benefits to your code. It can also help an application scale by separating the aspects of state management from an object’s implementation. Still, before implementation, it is essential to consider the tradeoffs and how it can affect the application’s overall performance.


Wrapping Up The Memento Pattern in C#

In this article, I discussed the Memento Pattern in C# and how it can be used to restore the state of an object effortlessly. We covered the origin and principle of the Memento Pattern and explained its different components, including the Memento, Originator, Details, and CareTaker classes.

I also provided a detailed explanation of the steps required to implement the Memento Pattern in C#, including creating an Originator class, a Memento class, and a Caretaker class. I also discussed how to add ‘Undo’ functionality to the pattern and the benefits and tradeoffs of implementing it in your programs.

In conclusion, using the Memento Pattern in C# can lead to easy state restoration and provide a cleaner, more organized codebase. If you’re interested in more learning opportunities, subscribe to my free weekly newsletter and check out my YouTube channel!

Also published here.


Written by devleader | Helping software engineers level up! I share content for general software engineering and C#/dotnet development/
Published by HackerNoon on 2024/02/05