Memento Pattern in C#: Definition, Examples, Pros, Cons, and Use Cases
The Memento pattern in C# is a behavioral design pattern that captures and restores an object's internal state without exposing its implementation details.
The Memento pattern allows an object to save its current state into a separate snapshot object called a memento. Later, the object can restore itself to that previously saved state when needed. This pattern helps implement undo/redo functionality while preserving encapsulation. The main participants are the Originator (state owner), the Memento (state snapshot), and the Caretaker (state manager). In C#, the Memento pattern is commonly used in editors, games, transaction systems, workflow systems, and history management features.
Why We Use Memento Pattern in C#?
We use the Memento pattern in C# to:
• Save and restore object states
• Implement undo/redo functionality
• Preserve encapsulation
• Track object history
• Roll back failed operations
• Simplify state recovery logic
• Manage snapshots safely
• Reduce direct exposure of internal object data
When Should We Use Memento Pattern in C#?
The Memento pattern should be used when:
• Object states must be restored later
• Undo/redo functionality is required
• State history tracking is needed
• Direct state exposure should be avoided
• Checkpoint systems are required
• Transaction rollback mechanisms are needed
• Complex object states need snapshot support
Common Programming Problems Solved by Memento Pattern
• Undo/redo systems
• Save/load game progress
• Transaction rollback
• Text editor history
• Configuration recovery
• Workflow checkpointing
• State versioning
• Temporary state backups
Structure of Memento Pattern in C#
Typical participants:
• Originator
• Memento
• Caretaker
• Client
Basic workflow:
• Originator creates a snapshot
• Caretaker stores snapshot
• Object state changes
• Caretaker restores snapshot when needed
Momento Pattern Examples in C#
Example 1: Text Editor Undo System
A text editor should support undo functionality.
using System;
using System.Collections.Generic;
public class TextMemento
{
public string Content { get; }
public TextMemento(string content)
{
Content = content;
}
}
public class TextEditor
{
public string Content { get; set; }
public TextMemento Save()
{
return new TextMemento(Content);
}
public void Restore(TextMemento memento)
{
Content = memento.Content;
}
}
public class History
{
private Stack<TextMemento> history = new Stack<TextMemento>();
public void Save(TextMemento memento)
{
history.Push(memento);
}
public TextMemento Undo()
{
return history.Pop();
}
}
public class Program
{
public static void Main()
{
TextEditor editor = new TextEditor();
History history = new History();
editor.Content = "Version 1";
history.Save(editor.Save());
editor.Content = "Version 2";
Console.WriteLine(editor.Content);
editor.Restore(history.Undo());
Console.WriteLine(editor.Content);
}
}
Example 2: Game Save System
A game should save and restore player progress.
using System;
public class GameMemento
{
public int Level { get; }
public int Health { get; }
public GameMemento(int level, int health)
{
Level = level;
Health = health;
}
}
public class Game
{
public int Level { get; set; }
public int Health { get; set; }
public GameMemento Save()
{
return new GameMemento(Level, Health);
}
public void Restore(GameMemento memento)
{
Level = memento.Level;
Health = memento.Health;
}
}
public class Program
{
public static void Main()
{
Game game = new Game();
game.Level = 5;
game.Health = 80;
GameMemento save = game.Save();
game.Level = 10;
game.Health = 20;
game.Restore(save);
Console.WriteLine($"Level: {game.Level}");
Console.WriteLine($"Health: {game.Health}");
}
}
Example 3: Bank Transaction Rollback
A failed transaction should restore previous account balance.
using System;
public class AccountMemento
{
public decimal Balance { get; }
public AccountMemento(decimal balance)
{
Balance = balance;
}
}
public class BankAccount
{
public decimal Balance { get; private set; }
public BankAccount(decimal balance)
{
Balance = balance;
}
public void Deposit(decimal amount)
{
Balance += amount;
}
public void Withdraw(decimal amount)
{
Balance -= amount;
}
public AccountMemento Save()
{
return new AccountMemento(Balance);
}
public void Restore(AccountMemento memento)
{
Balance = memento.Balance;
}
}
public class Program
{
public static void Main()
{
BankAccount account = new BankAccount(1000);
AccountMemento backup = account.Save();
account.Withdraw(900);
Console.WriteLine("Current Balance: " + account.Balance);
account.Restore(backup);
Console.WriteLine("Restored Balance: " + account.Balance);
}
}
Most Known Real-World Use Cases in C#
• Text editor undo/redo systems
• Game save/load systems
• Database transaction rollback
• Drawing applications
• Workflow recovery systems
• IDE history management
• Form state recovery
• Snapshot/version management
Advantages of Memento Pattern in C#
• Preserves encapsulation
• Simplifies undo/redo implementation
• Enables state restoration
• Supports rollback operations
• Keeps state snapshots isolated
• Improves recovery mechanisms
• Reduces direct state manipulation
• Makes history tracking easier
Disadvantages (Weak Points) of Memento Pattern in C#
• Can consume large memory for many snapshots
• Snapshot management may become complex
• Large objects increase storage costs
• Caretaker can grow significantly
• Performance overhead in frequent saves
• Difficult with deeply nested object graphs
• May require cloning complex structures
Comparison with Similar Patterns
| Pattern | Main Purpose | State Storage | Encapsulation | Typical Usage | Main Difference from Memento |
|---|---|---|---|---|---|
| Memento | Save and restore object state | Snapshot objects | Strong | Undo/redo, rollback | Focuses on state preservation and restoration |
| State | Change behavior by internal state | Separate state classes | Moderate | Workflow systems, UI states | Changes behavior dynamically instead of saving snapshots |
| Command | Encapsulate operations | Command history | Strong | Task queues, undo systems | Stores actions rather than full object states |
| Prototype | Clone objects | Object copies | Moderate | Object duplication | Focuses on cloning instead of historical restoration |
| Flyweight | Reduce memory usage | Shared state | Low | Caching systems | Optimizes memory instead of preserving history |
Simplified UML-Style Structure
| Component | Responsibility |
|---|---|
| Originator | Creates and restores snapshots |
| Memento | Stores object state snapshot |
| Caretaker | Manages saved snapshots |
| Client | Requests save or restore operations |