In this article, I am going to discuss about Memento pattern and its implementation in C#. Memento pattern is a design pattern that will allow us to restore an object to its previous state. It's like roll backing the operations done on an object and restoring its values to previous state. Suppose, we had done three operations on an object, which had changed its internal state like properties. Now, we want the object need to be restored to a state, it was before second operation on it. By using this pattern, we can easily restore an object to its previous state with minimal lines of coding. This pattern logs the internal state of an object without violating encapsulation and restores it back, when we require it.
Participants in this Pattern:
-
Memento: This is the object which will store the internal state of Originator.
-
Originator: This is the one going to log the current internal state of an object.
-
CareTaker: This is the one going to safely keep memento's previous state for restoring back later.
Let's start its implementation in C#. Create a new console application and name it as MementoSample Now, add the below code to Program.cs
First, we are defining Memento as shown below:
//Memento
class EmployeeMemento
{
private string _empName;
private string _empID;
private double _sal;
public EmployeeMemento(string empName, string empID, double salary)
{
this._empName = empName;
this._empID = empID;
this._sal = salary;
}
public string EmpName
{
get { return _empName; }
set { _empName = value; }
}
public string EmpID
{
get { return _empID; }
set { _empID = value; }
}
public double Salary
{
get { return _sal; }
set { _sal = value; }
}
}
This is the definition of our DTO class. Now, we will define Originator as shown below:
//Originator
class Originator
{
//Start of structure same as Memento[EmployeeMemento]
private string _empName;
private string _empID;
private double _sal;
public string EmpName
{
get { return _empName; }
set { _empName = value;}
}
public string EmpID
{
get { return _empID; }
set { _empID = value;}
}
public double Salary
{
get { return _sal; }
set { _sal = value;}
}
//End of structure same as Memento[EmployeeMemento]
//Restore state
public void RestoreState(EmployeeMemento empMemento)
{
Console.WriteLine("Restoring State");
this.EmpID = empMemento.EmpID;
this.EmpName = empMemento.EmpName;
this.Salary = empMemento.Salary;
}
public EmployeeMemento SaveState()
{
Console.WriteLine("Saving State");
return new EmployeeMemento(_empName, _empID, _sal);
}
}
This class is used to save/restore state. Now, we will define Caretaker class as shown below:
//CareTaker
class Caretaker
{
private EmployeeMemento _empInfo;
public EmployeeMemento EmpMemento
{
set { _empInfo = value; }
get { return _empInfo; }
}
}
Now, we are done with all definitions. We will test it out by adding below code to Main method:
static void Main(string[] args)
{
Originator org = new Originator();
org.EmpID = "100";
org.EmpName = "test";
org.Salary = 2000;
Console.WriteLine("Initial Emp Name:" + org.EmpName);
Console.WriteLine("Initial Emp ID:" + org.EmpID);
Console.WriteLine("Initial Emp Salary:" + org.Salary);
Console.WriteLine("");
Caretaker taker = new Caretaker();
taker.EmpMemento = org.SaveState();
//Now,alter the state.
org.EmpID = "101";
org.EmpName = "test1";
org.Salary = 3000;
Console.WriteLine("Updated Emp Name:" + org.EmpName);
Console.WriteLine("Updated Emp ID:" + org.EmpID);
Console.WriteLine("Updated Emp Salary:" + org.Salary);
Console.WriteLine("");
//Now,do rollback.
org.RestoreState(taker.EmpMemento);
Console.WriteLine("Rollbacked Emp Name:" + org.EmpName);
Console.WriteLine("Rollbacked Emp ID:" + org.EmpID);
Console.WriteLine("Rollbacked Emp Salary:" + org.Salary);
Console.WriteLine("");
Console.ReadLine();
}
Run the application, the output will be as shown below:
I will outline the steps for implementing this pattern:
-
First, create your DTO [Memento] class.
-
Than, create Originator class with structure similar to Memento, and one method to save the state and other method to restore the state.
-
Now, create a CareTaker class for storing the internal state of the Memento. This class acts as storage for object's internal state.
We can still enhance this pattern to store multiple states of an object by using a generic list for storing the internal state of an object.
I am ending the things here. I am attaching source code for reference. I hope this article will be helpful for all.