joydip_kanjilal
Contributor

How to use the Memento design pattern in C#

how-to
Nov 27, 20174 mins
C#Small and Medium BusinessSoftware Development

Take advantage of the Memento design pattern to store and restore an object's state to support undo or rollbacks in your application.

geometric seamless pattern 123822240
Credit: Thinkstock

We use design patterns to solve common design problems and reduce the complexities in our source code. The Memento design pattern is a behavioral design pattern that can be used to provide an undo or rollback capability in an application, or simply to reset the state of an object in an ASP.Net web application, for example. By storing an object’s state to an external location called a Memento, this pattern allows that state to be restored to the object at a later time. Let’s explore how we can use the Memento design pattern in C#.

Every object has its internal state. A Memento gives us a way to save that state and restore it while still abiding by the principles of encapsulation, which dictate that non-public members of an instance of a class should not be available to the outside world. This is because the Memento is available only to the object whose state it has stored.

The participants in the Memento design pattern include a Memento, an Originator, and a Caretaker. While the Memento class stores the state of the object, the Originator creates the Memento and uses it to restore the state when needed. The Caretaker is responsible only for storing the Memento—it is not supposed to alter the Memento instance. 

Implementing the Memento pattern 

In this section we will implement the Memento design pattern in C#. We will create a simple program that has three classes – a Calculator class, a Memento class, and the client, i.e. the Main method.

Refer to the Calculator class given below.

    public class Calculator
    {
        int result;
        public Calculator(int i = 0)
        {
            result = 0;
        }
        public void SetResult(int i = 0)
        {
            this.result = 0;
        }
        public void Add(int x)
        {
            result += x;
        }
        public void Subtract(int x)
        {
            result -= x;
        }
        public int GetResult()
        {
            return result;
        }
        public Memento CreateMemento()
        {
            Memento memento = new Memento();
            memento.SetState(result);
            return memento;
        }
        public void SaveState (Memento memento)
        {
            result = memento.GetState();
        }
    }

Note the CreateMemento and SetMemento methods in the Calculator class. While the former creates a Momento instance, the latter retrieves the saved state and assigns the value back to the result variable.

The Memento class

The Memento class contains two methods, SetState and GetState. While the former is used to store the state information, the latter is used to retrieve the saved state.

public class Memento
    {
        int state;
        public int GetState()
        {
            return state;
        }
        public void SetState(int state)
        {
            this.state = state;
        }
    }

The client in this example is the Main method that creates an instance of the Calculator class and makes calls to the Add and Subtract methods to perform computation. In addition, Main saves the state information at a particular checkpoint by making a call to the SaveState method. Later, this saved state is restored and the value of the result variable is displayed at the console window. This is illustrated in the code snippet given below.

        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();
            calculator.Add(5);
            calculator.Add(10);
            calculator.Subtract(10);
            Memento checkPoint = calculator.CreateMemento();
            calculator.Add(100);
            Console.WriteLine(“The value of the result variable is: “+calculator.GetResult());
            calculator.SaveState (checkPoint);
            Console.WriteLine(“The value of the result variable at first checkpoint is: “ + calculator.GetResult());
            Console.Read();
        }

The complete Memento pattern example

Here is the complete program for your reference.

class Program
    {
        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();
            calculator.Add(5);
            calculator.Add(10);
            calculator.Subtract(10);
            Memento checkPoint = calculator.CreateMemento();
            calculator.Add(100);
            Console.WriteLine(“The value of the result variable is: “+calculator.GetResult());
            calculator.SaveState (checkPoint);
            Console.WriteLine(“The value of the result variable at first checkpoint is: “ + calculator.GetResult());
            Console.Read();
        }
    }

    public class Calculator
    {
        int result;
        public Calculator(int i = 0)
        {
            result = 0;
        }
        public void SetResult(int i = 0)
        {
            this.result = 0;
        }
        public void Add(int x)
        {
            result += x;
        }
        public void Subtract(int x)
        {
            result -= x;
        }
        public int GetResult()
        {
            return result;
        }
        public Memento CreateMemento()
        {
            Memento memento = new Memento();
            memento.SetState(result);
            return memento;
        }
        public void SetMemento(Memento memento)
        {
            result = memento.GetState();
        }
    }

    public class Memento
    {
        int state;
        public int GetState()
        {
            return state;
        }
        public void SetState(int state)
        {
            this.state = state;
        }
    }

The Memento design pattern gives us a handy way to store and retrieve an object’s state. You can take advantage of this pattern to perform an undo or a rollback. However, one of the downsides of using this pattern is that the process of saving an object’s state and restoring it later can take quite some time—i.e., it may be detrimental to the application’s performance. So, when using the Memento pattern, be sure to keep performance in mind. Finally, also be sure that the internal structure of your object is not exposed to the outside world.

joydip_kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author