Back to: Design Patterns in C# With Real-Time Examples
Memento Design Pattern in C# with Examples
In this article, I will discuss the Memento Design Pattern in C# with Examples. Please read our previous article discussing the Mediator Design Pattern in C# with Examples. The Memento Design Pattern falls under the category of Behavioral Design Pattern. As part of this article, we will discuss the following pointers.
- What is the Memento Design Pattern?
- Examples to Understand Memento Design Pattern.
- Understanding the Class or UML Diagram of Memento Design Pattern
- Implementation of Memento Design Pattern in C#.
- When to use Memento Design Pattern in Real-Time Applications?
What is the Memento Design Pattern?
The Memento Design Pattern in C# restores an object to its Previous State. You must use the Memento Design Pattern to perform undo or rollback operations in your application. That means the Memento Design Pattern captures an object’s internal state to be restored to that state later. It is especially useful when implementing undo functionality in an application.
Understanding Memento Design Pattern with an Example in C#:
Let us understand the Memento Design Pattern in C# with an example. Please have a look at the following image. As shown in the below image, on the left-hand side, we have an employee with Id =101, Name =John, Salary = 2Lakhs, Designation = Software Engineer, Address = London, and many more attributes. Later, we changed some of the properties, i.e., Salary to 3Lakhs and designation to Senior Software Engineer; we also changed some other employee attributes, shown on the right-hand side of the image below. That means we change the object state from State 1 to State 2.
After some time, let’s undo or roll back the employee information to its previous state, i.e., State 1. If this is your requirement, you must use the Memento Design Pattern and roll back the employee information to its previous state.
Understanding the Class or UML Diagram of Memento Design Pattern:
Let us understand the Class or UML Diagram of the Memento Design Pattern and its different components. Please look at the following image to understand the Class or UML Diagram. As you can see in the image below, three important classes (Originator, Memento, and Caretaker) are involved in the Memento Design Pattern.
So, the Roles and Responsibilities of each component are as follows:
- Originator: The Originator is a class that creates a memento object containing a snapshot of the Originator’s current state. It also restores the Originator to one of its previous states. The Originator class has two methods. One is CreateMemento, and the other one is SetMemento. The CreateMemento Method will Create a snapshot of the current state of the Originator and return that Memento, which we can store in the Caretaker for later use, i.e., for restoring purposes. The SetMemento method accepts the memento object, and this method is going to changes the Internal State of the Originator to one of its Previous States.
- Caretaker: The Caretaker class will hold the Memento objects for later use. This class acts as a store only. It never Checks or Modifies the contents of the Memento object. This class will have two methods, i.e., AddMemento and GetMemento. The AddMomento Method will add the memento, i.e., the internal state of the Originator, into the Caretaker. The GetMemento Method returns one of the Previous Originator Internal States, saved in the Caretaker.
- Memento: The Memento class holds information about the Originator’s saved state. That means it sets the internal state and gets the internal state of the Originator object. This class has one method called GetState, which will return the Internal State of the Originator. This class also has one parameterized constructor, which you can set the internal state of the originator.
If this is unclear now, don’t worry; once we explain one example, you can easily understand this design pattern.
Real-Time Example to Understand Memento Design Pattern in C#:
Let us first understand the Real-Time Example that we will implement using the Memento Design Pattern in C#. I bought a 42-inch LED TV whose cost was 60000 Rupees, which does not support USB, and I placed it in the hall. After some point, I thought, let’s buy a 46-inch LED TV. So, I bought a 46-inch LED TV whose cost is 80000 Rupees, and it supports USB and I want to place it in the hall. But already in the hall, a 42-inch LED TV is there. So, what I have to do is, I have to place the 42-inch LED TV in the storeroom and place this 46-inch LED TV in the hall.
Again, after some point, I am thinking of buying a 50-inch LED TV whose cost is 100,000 Rupees, which supports USB. So, I bought this 50-inch LED TV and want to place it in the hall. But in the hall, the 46-inch LED TV is already there. So, I have to take the 46-inch LED TV from the hall, put it in the storeroom, and then place the 50-inch LED TV in the hall.
After some point, I thought, let’s put the 42-inch LED TV in the hall as the clarity of the 50-inch LED TV is not that good. So, what I do is I have to take the 50-inch LED TV from the hall and put it in the storeroom, and from the storeroom, take the 42-inch LED TV and put it in the hall. So, basically, we are rollbacking to its previous state.
In this example, the Hall is the Originator where we will store the Memento Object, and the Store Room is the Caretaker which is keeping the Memento. Led TV is the Memento, i.e., it is used to hold the internal state of LED TV. This is one of the best examples of the Memento Design Pattern. So, in a scenario like this, we need to use the Memento Design Pattern in our Real-Time Application.
Implementation of Memento Design Pattern in C#:
Let us implement the above-discussed LED TV Real-Time Example using the Memento Design Pattern in C# step by step.
Step 1: Creating LED TV
This will be our Model Class, which will hold the Product Information, i.e., the LED TV details. So, create a class file with the name LEDTV.cs and copy and paste the following code. This LED TV class has three properties (i.e., Size, Price, and USBSupport), and we are initializing these three properties using the class constructor. This class also has a method called GetDetails, which returns the details of a Led TV.
namespace MementoDesignPattern { //This is the Model class that is going to hold the Product information i.e. Led TV Details public class LEDTV { //Properties of the LED TV public string Size { get; set; } public string Price { get; set; } public bool USBSupport { get; set; } //Initializing the Properties using Constructor public LEDTV(string Size, string Price, bool USBSupport) { this.Size = Size; this.Price = Price; this.USBSupport = USBSupport; } //Fetching the Details of the LedTV public string GetDetails() { return "LEDTV [Size=" + Size + ", Price=" + Price + ", USBSupport=" + USBSupport + "]"; } } }
Step 2: Creating Memento
This will be a class that holds the information about the Originator’s saved state. This class is going to stores and returns the internal state of the Originator object. So, create a class file named Memento.cs and copy and paste the following code. Here, the LedTV is the Internal State of the Originator, and we are initializing that LedTV internal state using the Constructor. This class has one method, i.e., GetDetails, which is used to return the internal state details of the originator, i.e., LedTV. The following Memento class code is self-explained, so please go through the comment lines for a better understanding.
namespace MementoDesignPattern { //This is going to be a class that holds the information about the Originator’s saved state. //Stores the internal state of the Originator object. public class Memento { //The following Variable is going to Hold the Internal State of the Originator object public LEDTV LedTV { get; set; } //Initializing the Internal State of Originator Object using Constructor public Memento(LEDTV ledTV) { LedTV = ledTV; } //This Method is going to return the Internal State of the Originator public string GetDetails() { return "Memento [LedTV=" + LedTV.GetDetails() + "]"; } } }
Step 3: Creating Caretaker
This will be a class that is used to hold the Memento objects for later use. This class acts as a store only. It will never Check or Modify the contents of the Memento object. So, create a class named Caretaker.cs and copy and paste the following code. In our example, this is nothing but the Storeroom, where we will store the LED TVs not used in the Hall. This class has two methods. The AddMemento method is used to add a memento to the LedTvList collection property, and the GetMemento method is used to return a memento object based on the Index position. The following Caretaker class code is self-explained, so please go through the comment lines for a better understanding.
using System; using System.Collections.Generic; namespace MementoDesignPattern { //This is going to be a class that is used to hold a Memento object for later use. //This acts as a store only; it never Checks or Modifies the contents of the Memento object. public class Caretaker { //This variable is going to hold the List of Mementos that are used by the Originator. private List<Memento> LedTvList = new List<Memento>(); //This Method will add the memento i.e. the internal state of the Originator into the Caretaker i.e. Store Room public void AddMemento(Memento m) { LedTvList.Add(m); Console.WriteLine("LED TV's snapshots Maintained by CareTaker :" + m.GetDetails()); } //This Method is used to return one of the Previous Originator Internal States which saved in the Caretaker public Memento GetMemento(int index) { return LedTvList[index]; } } }
Step 4: Creating Originator
This class will create a memento object containing a snapshot of the Originator’s current state. It also provides the functionality to restore the Originator to one of its previous stored states. So, create a class file named Originator.cs and copy and paste the following code. In our example, this is the Hall where we need to place the LED TV. Here, the CreateMemento method is used to create a snapshot of the current state of the Originator, i.e., Current LedTV, and return that Memento, which we can store in the Caretaker, i.e., in the Store Room. The SetMemento method changes the Internal State of the Originator to one of its Previous States. The GetDetails method returns the Details of the Current Internal State of the Originator. The following Originator class code is self-explained, so please go through the comment lines for a better understanding.
namespace MementoDesignPattern { //This is going to be a class that creates a memento object containing a snapshot of the Originator's current state. //It also restores the Originator to a previously stored state. public class Originator { //This Property is used to store the current state of the Originator public LEDTV LedTV; //It will Create a snapshot of the current state of the Originator i.e. Current LedTV //and return that Memento which we can store in the Caretaker i.e. in the Store Room public Memento CreateMemento() { return new Memento(LedTV); } //This Method is going to change the Internal State of the Originator to one of its Previous State public void SetMemento(Memento memento) { LedTV = memento.LedTV; } //This Method is going to return the Details of the Current Internal State of the Originator public string GetDetails() { //To Fetch the Details, internally it is calling the GetDetails method on LedTV Object return "Originator [LEDTV=" + LedTV.GetDetails() + "]"; } } }
Step 5: Client
The Main method of the Program class is going to be the Client in our Example. So, please modify the Main method of the Program class as shown below. The following is used to explain the Memento Design Pattern. The following Client Code is self-explained, so please go through the comment lines for a better understanding.
using System; namespace MementoDesignPattern { class Program { static void Main(string[] args) { //Creating an Instance of the Originator and setting the current state as a 42-Inch Led TV Originator originator = new Originator { LedTV = new LEDTV("42-Inch", "60000", false) }; //Storing the Internal State (Memento i.e. the Current Led TV) of the Originator in the Caretaker i.e. Store Room //First, Create an instance of the Caretaker Caretaker caretaker = new Caretaker(); //Second Create a snapshot or memento of the current internal state of the originator Memento memento = originator.CreateMemento(); //Third, store the memento or snapshot in the store room i.e. Caretaker caretaker.AddMemento(memento); //Changing the Originator Current State to 46-Inch originator.LedTV = new LEDTV("46-Inch", "80000", true); //Again storing the Internal State (Memento) of the Originator in the Caretaker i.e. Store Room //Create the memento or snapshot of the current internal state of the originator memento = originator.CreateMemento(); //Store the memento in the Caretaker caretaker.AddMemento(memento); //Again, Changing the Originator Current State to 50-Inch originator.LedTV = new LEDTV("50-Inch", "100000", true); //The Current State of the Originator is now 50-Inch Led TV Console.WriteLine("\nOrignator Current State : " + originator.GetDetails()); //Restoring the Originator to one of its previous states //We have added two Memento to the Caretaker //Index-0 means the First memento i.e. 42 Inch LED TV //Index-1 means the Second memento i.e. 46 Inch LED TV Console.WriteLine("\nOriginator Restoring to 42-Inch LED TV"); originator.SetMemento(caretaker.GetMemento(0)); Console.WriteLine("\nOrignator Current State : " + originator.GetDetails()); Console.ReadKey(); } } }
Output:
When to Use the Memento Design Pattern in Real-Time Applications?
The Memento Design Pattern is useful when restoring an object to one of its previous states. It’s essentially an “undo” mechanism for object states. Here are some scenarios in real-time applications where the Memento pattern can be useful:
- Editor Applications: Text editors, image editing software, or any software that offers undo functionality can utilize the Memento pattern to save content states for every change. When a user presses “Undo”, the software retrieves the last saved state from the memento.
- Gaming: Many games allow players to save their progress. The saved game state is a memento. When you load a saved game, you’re restoring the game to its state when you saved it.
- Database Transactions: When performing complex transactions, sometimes you must roll back to a previous state if an error occurs. Memento can help capture the database’s state before performing operations.
- Serialization: Serializing an object to store or send over a network can be seen as creating a memento. The serialized state can be used to restore the object if needed.
- VM Snapshots: Virtualization software allows administrators to take snapshots (or mementos) of a virtual machine’s state. They can restore the VM to a previous snapshot if something goes wrong.
- State Management: Some applications have complex state management needs. For instance, web apps with complicated client-side interactivity might use a state management library or system to manage and navigate between states. Memento patterns can help in storing and restoring these states.
- Browser History: Each webpage visit can be thought of as a state. The browser’s back and forward buttons can be seen as restoring to a previous or next memento.
- Caretaker Operations: Operations like configuration management tools where you want to keep a history of configurations and be able to roll back to a previous configuration if needed.
When considering the use of the Memento pattern, keep the following in mind:
- Memory Implications: Depending on the size of the object’s state and how often mementos are created, the pattern can consume a significant amount of memory.
- Encapsulation: The memento should not expose the internal state details of the originator. Ensure that you’re not breaking encapsulation when implementing the pattern.
So, any situation where you anticipate the need to revert to an earlier state or where maintaining a history of states is beneficial is a potential candidate for the Memento pattern.
In the next article, I will discuss the Real-Time Examples of Memento Design Patterns in C#. In this article, I try to explain the Memento Design Pattern in C# with Examples. I hope you enjoy this Memento Design Pattern in C# with Examples article.