Memento
Problemet
Du vill kunna spara ett objekts tillstånd och återställa det senare (Ångra-funktionalitet) — men utan att exponera objektets interna fält publikt bara för att en annan klass ska kunna läsa och återställa dem. Det skulle bryta inkapslingen.
Lösningen
Tre roller: Originator (objektet vars tillstånd ska sparas), Memento (en oföränderlig ögonblicksbild), Caretaker (håller reda på ögonblicksbilderna, men läser aldrig deras innehåll).
// Memento — en oföränderlig ögonblicksbild, bara Originator kan läsa dess innehållpublic class TextMemento{ public string Innehåll { get; } internal TextMemento(string innehåll) => Innehåll = innehåll;}
// Originator — objektet vars tillstånd ska kunna sparas/återställaspublic class TextEditor{ public string Text { get; private set; } = "";
public void Skriv(string text) => Text += text;
public TextMemento SparaTillstånd() => new(Text);
public void ÅterställTillstånd(TextMemento memento) => Text = memento.Innehåll;}
// Caretaker — håller historiken, men bryr sig aldrig om VAD som faktiskt sparatspublic class HistorikHanterare{ private readonly Stack<TextMemento> _historik = new();
public void SparaCheckpoint(TextEditor editor) => _historik.Push(editor.SparaTillstånd());
public void Ångra(TextEditor editor) { if (_historik.Count > 0) editor.ÅterställTillstånd(_historik.Pop()); }}var editor = new TextEditor();var historik = new HistorikHanterare();
editor.Skriv("Hej");historik.SparaCheckpoint(editor);
editor.Skriv(" världen!");Console.WriteLine(editor.Text); // Hej världen!
historik.Ångra(editor);Console.WriteLine(editor.Text); // Hej — tillbaka till checkpointenHistorikHanterare (Caretaker) lagrar TextMemento-objekt utan att någonsin läsa deras Innehåll direkt i sin egen logik — den bara skickar dem tillbaka till TextEditor (Originator), som är den enda som vet hur de ska tolkas.
Släktskap med Command
Command och Memento kompletterar varandra ofta i praktiska Ångra-implementationer: Command kapslar in vad som gjordes och hur det görs om (Undo()), medan Memento kapslar in tillståndet som ska återställas. Ett enkelt Ångra kan klara sig med bara Command; ett Ångra som kräver att återställa komplext, sammansatt tillstånd lutar sig ofta på Memento.
TL;DR
Memento sparar en ögonblicksbild av ett objekts tillstånd i ett separat, oföränderligt objekt — utan att bryta inkapslingen, eftersom bara originalobjektet vet hur innehållet ska tolkas. Grunden för Ångra/Gör om-funktionalitet.