The memento pattern captures an object's state at a point in time and allows that state to be restored later — without exposing the object's internal representation. It is a behavioural pattern and is the mechanism behind undo/redo functionality in most applications.
Three Actors
- Memento — an immutable snapshot of the originator's state. The caretaker stores it but must not read or modify its contents.
- Originator — owns the live state. Creates mementos from its current state and restores its state from a given memento.
- Caretaker — maintains the history list of mementos. It can save and retrieve mementos but never inspects them.
Originator
csharp
// Originator — holds the live state and knows how to snapshot / restore it
public class Originator
{
public string Article { get; set; }
public void Set(string newArticle)
{
Console.WriteLine(quot;Setting article: '{newArticle}'");
Article = newArticle;
}
// Capture current state into a memento
public Memento StoreInMemento()
{
Console.WriteLine(quot;Saving to memento: '{Article}'");
return new Memento(Article);
}
// Restore state from a previously saved memento
public string RestoreFromMemento(Memento memento)
{
Article = memento.Article;
Console.WriteLine(quot;Restored: '{Article}'");
return Article;
}
}Memento
csharp
// Memento — a read-only snapshot of the originator's state.
// The caretaker stores these but must not inspect or modify their contents.
public class Memento
{
public string Article { get; }
public Memento(string article)
{
Article = article;
}
}Caretaker
csharp
// Caretaker — manages a history of mementos without knowing what's inside them
public class Caretaker
{
private List<Memento> _saved = new List<Memento>();
public void AddMemento(Memento m) => _saved.Add(m);
public Memento GetMemento(int index) => _saved[index];
}Usage
csharp
Caretaker caretaker = new Caretaker();
Originator originator = new Originator();
originator.Article = "My article 1";
caretaker.AddMemento(originator.StoreInMemento()); // save state 0
originator.Article = "My article 2";
caretaker.AddMemento(originator.StoreInMemento()); // save state 1
// Restore to the first saved state
Memento first = caretaker.GetMemento(0);
originator.RestoreFromMemento(first);
Console.WriteLine(originator.Article); // My article 1