Memento Design Pattern Using C#

In this article, we will be explaining the Memento Design Pattern, that is part of the Behavioral Design Patterns. The purpose of the Memento Design Pattern is to maintain the state or values of an instance of a class. This state can be re-stored when required. It is like creating a checkpoint or snapshot of data at a given time. In case any issue is encountered in subsequent processing, we can restore the checkpoint or snapshot data. In other words, it provides the ability to do the Undo type of functionality.

So let's explain this pattern in detail now.

What is the Memento Pattern?

According to the GoF's definition, what this pattern does is:

Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.

A Real world example

Let's use an example of a computer game, where we have a player who will need to cross levels 1 to 5 to complete the game and will score different scores at each level. We will create a checkpoint for this player at level 1, with some initial score at a specific instance of time, and store a snapshot of its data. Then we will update the score, level and time of the player. Now with some business rule, say the player looses a life, he will again need to start from that checkpoint. So when he starts again from the checkpoint, we will restore the snapshot data and proceed further accordingly. In order to do this, we will divide the system into the following components.

  1. Originator or MainClass

    This is the main class of the system that maintains the data of the player, in other words its level, score and so on and for which we want to create a snapshot of the data. In our case, it will be a PlayerStatistics class, with 3 properties named Level, Score and CheckPointTime. These are the properties or the data of the player, for which we want to create a snapshot.
     
  2. Memento

    This class is used to store the snapshot of the Originator class data. In our case, it will be the CheckPointMemento class, only with properties, for which we want to store the data, in other words for each of the properties that we want to have in the snapshot, we create a property in the memento class.
     
  3. CareTakerClass

    This is like a container class, that holds the Memento class instance, that further holds the snapshot of the original data. In our case, it will be CheckPointCareTaker, and will hold the memento instance using a property defined in it.

So, to start with, we create the following classes:

  • A PlayerStatistics class and its properties.
  • A CheckPointMemento class, with the properties for which we want to store the snapshot data of the PlayerStatistics class.
  • A CheckPointCareTaker class, that will act as a container for CheckPointMemento class.

See the classes below. These are the memento and caretaker classes.



Now we will create the main class PlayerStatistics and an important point to note here is that the PlayerStatistics class will have two methods, apart from the properties to hold the player data. These methods are :

  1. CreateCheckPoint()

    This method will be used to return the instance of the memento that is storing the data of which we would like to create a snapshot. The instance returned by this method will be added to the container or the CheckPointCareTaker class, by setting the property.
     
  2. RestoreCheckPoint()

    This method will receive the memento class instance or you can say the snapshot data that we added at the checkpoint. The data received will then be returned to the original properties.

See the complete code for the Main/originator class, with the properties and the two methods explained above.



Now we have set up the initial code. It's time to write the client code. So we start by setting some initial data for the player. Then we will store the data in a memento instance and add it to the caretaker container class. Further we will change the data and then finally retrieve the stored data from the memento instance. So our code will be like the following:



How is it working ?

Let's explain the client code now.

  • In Step 1, we simply set the properties of the player data and print them.
  • In Step 2, we call the CreateCheckPoint() method in the main class, and generate the instance of the memento class type. This instance is then assigned to the CheckPointCareTaker class, that acts as a container here to hold the snapshot data.
  • In Step 3, we simply update the data and print it, like we did in Step 1.
  • In Step 4, we basically perform the undo operation and retrieve the original data that we had at the start. This is done by calling the RestoreCheckPoint method in the main class and passing it the data from the container or caretaker class. The data received is then set back to the properties and printed again.

So this was all about the Memento Design Pattern. I hope you enjoyed reading it!!