Memento Design Pattern
You can see this and other great articles on design patterns here.
The Memento Design Pattern allows you to save historical states of an object and restore the object back from the historical states. As your application is progressing, you may want to save checkpoints in your application and restore back to those checkpoints later. An example are the checkpoints saved in a video game where the user is allowed to go back to the stages that they have already conquered. Another example are the undo operations in a word processing application.
Let’s look at the UML of the memento pattern first, then we will look at some code to see how it works. Below is the UMLof the Memento Design Pattern:
- The
Originator
class is the objects that will be saved and restored later:
- The
state
variable contains information that represents the state of theOriginator
object. This is the variable that we save and restore.
- The
CreateMemento
method is used to save the state of theOriginator.
It creates aMemento
object by saving thestate
variable into theMemento
object and return it. This is for recording the state of theOriginator
.
- The
SetMemento
method restores theOriginator
by accepting aMemento
object, unpackage it, and sets itsstate
variable using thestate
variable from theMemento
. This is for restoring the state of theOriginator
using the information that was previously saved in theMemento
.
- The
Memento
class stores the historical information of theOriginator
. The information is stored in itsstate
variable.
- The
Caretaker
class manages the list ofMemento
. This is the class for the client code to access.
The key to the Memento Design Pattern is that the client code will never access the Memento
object, all of the interactions are done through the Caretaker
class. The client code does not need to be concerned about how the states are stored and retrieved.
Below are the implementation code and the output of the Memento Design Pattern. It shows that we can save the states of the Originator
and restore it back at a later point in time. Notice that the client code does not need to access the Memento
objects:
class Program { static void Main(string[] args) { Originator<string> orig = new Originator<string>(); orig.SetState("state0"); Caretaker<string>.SaveState(orig); //save state of the originator orig.ShowState(); orig.SetState("state1"); Caretaker<string>.SaveState(orig); //save state of the originator orig.ShowState(); orig.SetState("state2"); Caretaker<string>.SaveState(orig); //save state of the originator orig.ShowState(); //restore state of the originator Caretaker<string>.RestoreState(orig, 0); orig.ShowState(); //shows state0 } } //object that stores the historical state public class Memento<t> { private T state; public T GetState() { return state; } public void SetState(T state) { this.state = state; } } //the object that we want to save and restore, such as a check point in an application public class Originator<t> { private T state; //for saving the state public Memento<t> CreateMemento() { Memento<t> m = new Memento<t>(); m.SetState(state); return m; } //for restoring the state public void SetMemento(Memento<t> m) { state = m.GetState(); } //change the state of the Originator public void SetState(T state) { this.state = state; } //show the state of the Originator public void ShowState() { Console.WriteLine(state.ToString()); } } //object for the client to access public static class Caretaker<t> { //list of states saved private static List<memento><t>> mementoList = new List<memento><t>>(); //save state of the originator public static void SaveState(Originator<t> orig) { mementoList.Add(orig.CreateMemento()); } //restore state of the originator public static void RestoreState(Originator<t> orig, int stateNumber) { orig.SetMemento(mementoList[stateNumber]); } }
Liked this article? You can see this and other great articles on design patterns here.