BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Design Patterns
.NET 1.1+

Memento Design Pattern

The memento pattern is a design pattern that permits the current state of an object to be stored without breaking the rules of encapsulation. The originating object can be modified as required but can be restored to the saved state at any time.

What is the Memento Pattern?

The memento pattern is a Gang of Four design pattern. This is a behavioural pattern as it defines a manner for controlling communication between classes or entities. The memento pattern is used to capture the current state of an object and store it in such a manner that it can be restored at a later time. Importantly, the pattern allows for the internal state of an object to be saved without breaking the rules of encapsulation. This design pattern is commonly used to provide an application with Undo functionality.

Implementing the Memento Pattern

Memento Design Pattern UML

The UML class diagram above describes an implementation of the memento design pattern. The items in the diagram are described below:

  • Originator. This is the class whose state is to be stored. The Originator includes a method, named "CreateMemento", that is used to generate a Memento object containing a snapshot of the Originator's current state. It also includes the "SetMemento" method, which restores the Originator to a previously stored state.
  • Memento. The Memento class is used to hold the information from an Originator's state. The amount of information held is controlled by the Originator. The Memento can provide protection against change to the stored state by including a very limited interface with no means of modifying the values it holds.
  • Caretaker. The Caretaker class is used to hold a Memento object for later use. The Caretaker provides storage only; it should neither examine nor modify the contents of the Memento object. In the UML diagram and the examples in this article the Caretaker holds a single Memento object. It can be modified to hold a collection of Mementos to support multi-level undo and redo functionality.

The following shows the basic code of the memento design pattern implemented using C#. To keep the sample code short, it uses C# 3.0 automatically implemented properties. For users of the .NET framework version 2.0 and earlier, these properties should be expanded to include get and set accessors and a backing store variable. The state in this code is represented by a single private string.

public class Originator
{
    private string _state;

    public Memento CreateMemento()
    {
        return new Memento(_state);
    }

    public void SetMemento(Memento memento)
    {
        _state = memento.GetState();
    }
}


public class Memento
{
    private string _state;

    public Memento(string state)
    {
        _state = state;
    }

    public string GetState()
    {
        return _state;
    }
}


public class Caretaker
{
    public Memento Memento { get; set; }
}

Example Memento

In the remainder of this article we will create an example of the memento design pattern. This example will show some of the classes used in a single-level undo system for a library system. We will include an originator class that represents book details being edited by a user. If the user makes an error, they can perform an undo operation to revert a book to its previous state. Note the private variable holding the UTC timestamp for the last edit time. Also note that the memento has been modified slightly to present the state as read-only properties instead of as a method. This simplifies the retrieval of the values.

public class Book
{
    private string _isbn;
    private string _title;
    private string _author;
    private DateTime _lastEdited;

    public string ISBN
    {
        get { return _isbn; }
        set
        {
            _isbn = value;
            SetLastEdited();
        }
    }

    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            SetLastEdited();
        }
    }

    public string Author
    {
        get { return _author; }
        set
        {
            _author = value;
            SetLastEdited();
        }
    }

    public Book()
    {
        SetLastEdited();
    }

    private void SetLastEdited()
    {
        _lastEdited = DateTime.UtcNow;
    }

    public Memento CreateUndo()
    {
        return new Memento(_isbn, _title, _author, _lastEdited);
    }

    public void RestoreFromUndo(Memento memento)
    {
        _title = memento.Title;
        _author = memento.Author;
        _isbn = memento.ISBN;
        _lastEdited = memento.LastEdited;
    }

    public void ShowBook()
    {
        Console.WriteLine(
            "{0} - '{1}' by {2}, edited {3}.", ISBN, Title, Author, _lastEdited); 
    }
}


public class Memento
{
    public string ISBN { get; private set; }
    public string Title { get; private set; }
    public string Author { get; private set; }
    public DateTime LastEdited { get; private set; }

    public Memento(string isbn, string title, string author, DateTime lastEdited)
    {
        ISBN = isbn;
        Title = title;
        Author = author;
        LastEdited = lastEdited;
    }
}


public class Caretaker
{
    public Memento Memento { get; set; }
}
18 July 2009