C# Memento Pattern

Summary: in this tutorial, you’ll learn how to use the C# Memento pattern to store the internal state of an object externally without violating the object’s encapsulation.

Introduction to C# Memento pattern

Sometimes, you want to store the internal state of an object externally so that you can restore it later but you don’t want to violate the object’s encapsulation. To do that, you can use the Memento design pattern.

The Memento pattern is a behavioral design pattern that captures and externalizes the internal state of an object so that the object can be restored to the saved state later, without violating encapsulation.

The following diagram illustrates the Memento pattern:

C# Memento Pattern

The Memento pattern has the following participants:

  • Memento is responsible for storing the internal state of the Originator object. It may store as much or as little of the internal state depending on the Originator object’s needs.
  • Originator is an object whose state needs to be saved and restored. The Originator object creates a Memento object that captures a snapshot of its current internal state. The Originator uses the Memento to restore its internal state.
  • Caretaker is in charge of managing the Mementos. The Caretaker object requests a Memento object from the Originator, stores it, and later uses it to restore the Originator.

In practice, you’ll find the Memento pattern helpful in the following cases:

  • Undo/rollback: You can use the Memento pattern to implement undo/rollback functionality, where you can restore an object’s state to a previous state. This is useful in applications where users make changes that they want to undo, like in a text editor.
  • Versioning: You can also use the Memento pattern to implement versioning, where you can save an object’s state at different points in time. This is useful in applications where it is important to keep track of changes made to an object over time, such as in a document management system.

C# Memento pattern example

The following program illustrates how to implement the Memento pattern in C#:

namespace MemetoPattern;

public class Memento
{
    public string? State
    {
        get;
        set;
    }

    public Memento(string? state)
    {
        State = state;
    }
}

public class Originator
{
    public string? State
    {
        get; set;
    }
    public void RestoreState(Memento memento)
    {
        State = memento.State;
    }

    public Memento SaveState()
    {
        return new Memento(State);
    }
}

public class Caretaker
{
    public static void Main(string[] args)
    {
        var originator = new Originator
        {
            State = "State 1"
        };

        // Save the state
        var memento = originator.SaveState();

        // Change the state
        originator.State = "State 2";

        // Restore the state from the memento object
        originator.RestoreState(memento);

        // Display the state
        Console.WriteLine(originator.State); // State 1
    }
}Code language: C# (cs)

Output:

State 1Code language: C# (cs)

How it works.

First, define the Memento class that captures the state of an object. The state is a simple nullable string:

public class Memento
{
    public string? State
    {
        get;
        set;
    }

    public Memento(string? state)
    {
        State = state;
    }
}Code language: C# (cs)

Second, define the Originator object whose internal state is saved by a Memento object:

public class Originator
{
    public string? State
    {
        get; set;
    }
    public void RestoreState(Memento memento)
    {
        State = memento.State;
    }

    public Memento SaveState()
    {
        return new Memento(State);
    }
}Code language: C# (cs)

The Originator class has a State property as a string and the SaveState() and RestoreState() methods.

The SaveState() method returns a new Memento object with the current State. And the RestoreState restores the State from a Memento object by assigning the State property to the State of the Memento object.

Third, define the Caretaker class that creates an Originator object with the State 1, saves its state into a Memento object, changes the state of the Originator object to “State 2”, and restores the state of the Originator object to “State 1” using the Memento object:

public class Caretaker
{
    public static void Main(string[] args)
    {
        var originator = new Originator
        {
            State = "State 1"
        };

        // Save the state
        var memento = originator.SaveState();

        // Change the state
        originator.State = "State 2";

        // Restore the state from the memento object
        originator.RestoreState(memento);

        // Display the state
        Console.WriteLine(originator.State); // State 1
    }
}Code language: C# (cs)

It’s possible to save multiple states of the originator object and restore it to a specific state later. For example:

public class Caretaker
{
    public static void Main(string[] args)
    {
        // 
        var savedStates = new List<Memento>();

        var originator = new Originator
        {
            State = "State 1"
        };

        // Save the State 1
        savedStates.Add(originator.SaveState());

        // Change the state
        originator.State = "State 2";

        // Save the State 2
        savedStates.Add(originator.SaveState());

        originator.State = "State 3";

        // Restore the intial state
        originator.RestoreState(savedStates[0]);

        Console.WriteLine(originator.State); // State 1

    }
}Code language: C# (cs)

Output:

State 1Code language: C# (cs)

Summary

  • Use the Memento pattern to store the internal state of an object externally without violating encapsulation.
Was this tutorial helpful ?