The Memento pattern provides the abilitiy to restore an object to its previous state later.
- The internal state of an object should be saved externally so that the object can be restored to this state later.
- The object's encapsulation must not be violated.
Make an object (originator) itself responsible for
- saving its internal state to a
mementoobject and - restoring to a previous state from a
mementoobject.
Only the originator that created a memento is allowed to access it.
A client (caretaker) can request a memento from the originator to save the internal state. It can also pass a memento back to the originator to restore to a previous state.
- Memento
- is a value object that stores internal state of the Originator object.
- It is common practice to make Memento immutable and pass it data only once, via constructor.
- Originator
- creates a memento containing a snapshot of its current internal state.
- uses the memento to restore its internal state
- Caretaker
- keeps a history of originator's state by storing a stack of mementos
- never operates on or examines the contents of a memento
- When originator has to go back in history, the caretaker passes the last memento to the originator's restoration method.
- Mementos are passive. Only the originator that created a memento will assign or retrieve its state.
- Does not violate the originator's encapsulation.
- Keeping the saved state external from the originator helps to maintain cohesion.
- Provides easy-to-implement recovery capability.
- Saving and restoring state can be time consuming.
- It may require lots of memory if clients create mementors too often.
- Clients should track the originator's lifecycle in order to destroy obsolete mementos.
Memento
[Serializable]
class Memento
{
public string State { get; }
public Memento(String state)
{
this.State = state;
}
}Originator
class Originator
{
private String _state;
public void SetState(String state)
{
this._state = state;
Console.WriteLine($"State is set to {state}");
}
public Memento Save()
{
Console.WriteLine($"Saving state to Memento");
return new Memento(this._state);
}
public void Restore(Memento m)
{
this._state = m.State;
Console.WriteLine($"State is restored from Memento: {_state}");
}
}CareTaker
IList<Memento> mementoes = new List<Memento>();
Originator originator = new Originator();
originator.SetState("State 1");
originator.SetState("State 2");
mementoes.Add(originator.Save()); // checkpoint 1
originator.SetState("State 3");
mementoes.Add(originator.Save()); // checkpoint 2
originator.SetState("State 4");
originator.Restore(mementoes[0]); // restore to checkpoint 1Output
State is set to State 1
State is set to State 2
Saving state to Memento
State is set to State 3
Saving state to Memento
State is set to State 4
State is restored from Memento: State 2
-
Command can use Mementos to maintain state for undoable operations.
-
Iterator - Mementos can be used for iteration as described earlier.
