Memento Pattern¶
Category: Behavioral Pattern
Overview¶
Capture and externalize an object's internal state without violating encapsulation, so that the object can be restored to this state later. This pattern is useful for implementing undo/redo functionality, checkpoints, and snapshots while preserving object encapsulation.
Usage Guidelines¶
Use when:
- Need to implement undo and redo functionality
- Want to save object state at specific points in time
- Need to rollback to previous states
- Creating save points in games or applications
Avoid when:
- State is simple and can be easily recreated
- Storing many mementos consumes too much memory
- All state is already public
- Never need to restore previous states
Implementation¶
from __future__ import annotations
from typing import Any
class Memento:
"""Stores the internal state of the Originator."""
def __init__(self, state: Any) -> None:
"""Initialize memento with state."""
self._state = state
def get_state(self) -> Any:
"""Get the stored state."""
return self._state
class TextEditor:
"""Originator class that creates and restores mementos."""
def __init__(self) -> None:
"""Initialize text editor with empty content."""
self._content: str = ""
def write(self, text: str) -> None:
"""Add text to the editor."""
self._content += text
def get_content(self) -> str:
"""Get current content."""
return self._content
def save(self) -> Memento:
"""Create a memento with current state."""
return Memento(self._content)
def restore(self, memento: Memento) -> None:
"""Restore state from memento."""
self._content = memento.get_state()
class History:
"""Caretaker that manages mementos."""
def __init__(self) -> None:
"""Initialize empty history."""
self._mementos: list[Memento] = []
def save(self, editor: TextEditor) -> None:
"""Save current editor state."""
self._mementos.append(editor.save())
def undo(self, editor: TextEditor) -> bool:
"""Undo to previous state."""
if len(self._mementos) <= 1:
if self._mementos:
self._mementos.pop()
editor.restore(Memento("")) # Restore to empty
return True
return False
self._mementos.pop() # Remove most recent state
editor.restore(self._mementos[-1]) # Restore to previous state
return True
Usage¶
# Text editor with undo
editor = TextEditor()
history = History()
editor.write("Hello ")
history.save(editor)
editor.write("World")
history.save(editor)
editor.write("!")
print(editor.get_content()) # "Hello World!"
history.undo(editor)
print(editor.get_content()) # "Hello World"
history.undo(editor)
print(editor.get_content()) # "Hello "
Trade-offs¶
Benefits:
- Encapsulation preserved with internal state saved without exposing structure
- Simplified originator that doesn't manage its own history
- Easy to implement undo and redo operations
- Can save multiple snapshots at different points
Drawbacks:
- Storing many mementos uses significant memory
- Creating mementos can be expensive for large objects
- Caretaker must manage memento lifecycle
- Large state makes mementos expensive
Real-World Examples¶
- Text editors with undo/redo functionality
- Version control systems like Git with commits and checkpoints
- Database transactions with rollback and commit
- Games with save points and quick saves
Related Patterns¶
- Command
- Iterator
- Prototype
- Caretaker
API Reference¶
design_patterns.behavioral.memento
¶
Memento Pattern Module
The Memento pattern captures and externalizes an object's internal state without violating encapsulation, so that the object can be restored to this state later. It's useful for implementing undo/redo functionality, checkpoints, and snapshots.
Example
Text editor with undo functionality:
CheckpointManager
¶
Manages game checkpoints.
Source code in src/design_patterns/behavioral/memento.py
__init__()
¶
clear_checkpoints()
¶
get_checkpoint_count()
¶
Get number of saved checkpoints.
Returns:
| Type | Description |
|---|---|
int
|
Number of checkpoints. |
load_checkpoint(game, index=-1)
¶
Load a checkpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
game
|
GameState
|
Game state to restore. |
required |
index
|
int
|
Checkpoint index (-1 for most recent). |
-1
|
Returns:
| Type | Description |
|---|---|
bool
|
True if checkpoint was loaded successfully. |
Source code in src/design_patterns/behavioral/memento.py
ConfigMemento
¶
Memento for configuration.
Source code in src/design_patterns/behavioral/memento.py
Configuration
¶
Configuration object with memento support.
Source code in src/design_patterns/behavioral/memento.py
__init__()
¶
Initialize configuration with defaults.
create_snapshot()
¶
Create a snapshot of current configuration.
Returns:
| Type | Description |
|---|---|
ConfigMemento
|
Memento with current settings. |
get(key, default=None)
¶
Get a configuration value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Setting key. |
required |
default
|
Any
|
Default value if key not found. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
Setting value or default. |
Source code in src/design_patterns/behavioral/memento.py
restore_snapshot(memento)
¶
Restore configuration from snapshot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
memento
|
ConfigMemento
|
Snapshot to restore. |
required |
set(key, value)
¶
Set a configuration value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
Setting key. |
required |
value
|
Any
|
Setting value. |
required |
GameMemento
¶
Memento for game state.
Source code in src/design_patterns/behavioral/memento.py
__init__(level, score, lives, position)
¶
Initialize game memento.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
Current level. |
required |
score
|
int
|
Current score. |
required |
lives
|
int
|
Remaining lives. |
required |
position
|
tuple[int, int]
|
Player position. |
required |
Source code in src/design_patterns/behavioral/memento.py
get_state()
¶
Get saved game state.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Dictionary containing game state. |
GameState
¶
Represents game state for checkpoint system.
Source code in src/design_patterns/behavioral/memento.py
__init__()
¶
add_score(points)
¶
Add points to score.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
int
|
Points to add. |
required |
advance_level()
¶
load_checkpoint(memento)
¶
Load from checkpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
memento
|
GameMemento
|
Checkpoint to load. |
required |
Source code in src/design_patterns/behavioral/memento.py
lose_life()
¶
save_checkpoint()
¶
Create a checkpoint.
Returns:
| Type | Description |
|---|---|
GameMemento
|
Memento with current game state. |
Source code in src/design_patterns/behavioral/memento.py
set_position(x, y)
¶
Set player position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
int
|
X coordinate. |
required |
y
|
int
|
Y coordinate. |
required |
History
¶
Caretaker that manages mementos.
Source code in src/design_patterns/behavioral/memento.py
__init__()
¶
get_history_size()
¶
Get number of saved states.
Returns:
| Type | Description |
|---|---|
int
|
Number of states in history. |
save(editor)
¶
Save current editor state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
editor
|
TextEditor
|
Editor to save. |
required |
undo(editor)
¶
Undo to previous state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
editor
|
TextEditor
|
Editor to restore. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if undo was successful, False if no history. |
Source code in src/design_patterns/behavioral/memento.py
Memento
¶
Stores the internal state of the Originator.
Source code in src/design_patterns/behavioral/memento.py
__init__(state)
¶
Initialize memento with state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
Any
|
State to store. |
required |
TextEditor
¶
Originator class that creates and restores mementos.