DevIQ
Memento Pattern
Memento Pattern
The Memento pattern - also known as the Token pattern - is used to externalize an object's internal state for restoration later, without violating encapsulation. This pattern is part of the patterns covered in Design Patterns by the Gang of Four. It is a behavioral pattern, as it allows you to add undo and replay behaviors to an object.
A memento holds an object's internal state to be retrieved later. Think of this like save points in a video game, stacks for tracking changes, or commits in source control. The key thing to note with the Memento pattern is that it captures an object's internal state without violating encapsulation.
When to Use Memento
This pattern is best suited for cases where objects need to be restored to a particular state. Cases for this include:
- Undo/redo in an editor application
- Rolling back objects to a previous state when cancelling an action
- Providing access to internal state without breaking encapsulation
Structure of Memento Pattern
There are three key classes to the memento pattern - Originator, Caretaker, and Memento.
- The Memento class holds state (
state
). This is accessible through two methods -GetState()
andSetState()
. - The Originator class has the state (
state
) to be stored in the memento. It can create mementos withCreateMemento()
. It can also set a memento withSetMemento(Memento m)
. - The Caretaker class is responsible for the safekeeping and does not perform work on a memento.
These classes work in the following way:
- The caretaker requests a memento for the originator with
CreateMemento()
. - The originator creates a new memento through
new Memento()
. - The originator sets the state of the memento using
SetState()
. - If the object needs to be restored to a previous state, the caretaker will pass the request to the originator using
SetMemento(memento)
. - The originator gets the previous state using
GetState()
.
The goal is to keep the mementos small. Also, the caretaker only deals with the memento through the originator. The caretaker never directly changes a memento. The caretaker only tracks the previous states. The originator handles the creation and restoring of mementos.
Sample Code for the Memento Pattern
Here is a how the Memento pattern could be implemented using C#:
using System;using System.Collections.Generic;
// Originator: The object whose state needs to be savedclass Originator{ private string _state;
public string State { // GetState() get { return _state; } // SetState() set { _state = value; Console.WriteLine("State set to: " + _state); } }
// Creates a memento with the current state public Memento CreateMemento() { return new Memento(_state); }
// Set the memento to a specific state public void SetMemento(Memento memento) { _state = memento.State; Console.WriteLine("State restored to: " + _state); }}
// Memento: Stores the internal state of the Originatorclass Memento{ public string State { get; }
public Memento(string state) { State = state; }}
// Caretaker: Manages and keeps track of multiple mementosclass Caretaker{ public List<Memento> Mementos { get; } = new List<Memento>();}
class Program{ static void Main(string[] args) { // Create an originator Originator originator = new Originator();
// Create a caretaker to manage mementos Caretaker caretaker = new Caretaker();
// Set the initial state and save it in a memento originator.State = "State 1"; caretaker.Mementos.Add(originator.CreateMemento());
// Change the state and save it in another memento originator.State = "State 2"; caretaker.Mementos.Add(originator.CreateMemento());
// Restore the state from the first memento originator.RestoreMemento(caretaker.Mementos[0]);
Console.ReadLine(); }}
Code examples for implementing undo/redo in a game can be seen in C# Design Patterns: Memento (Pluralsight). The companion code for the course is here: C# Design Patterns: Memento (GitHub)
Edit this page on GitHub