Memento and Visitor: Snapshots and Operations Over a Hierarchy
Architecture PatternsMemento saves an object's state in an opaque snapshot so you can restore it later (undo) without exposing its internals. Visitor adds new operations over a family of classes without editing them, by letting each class hand itself to the visitor: double dispatch.
Memento is a save-game file: the game writes its own state to a file only it can read, and loading it puts everything back. Visitor is a building inspector who walks through every kind of room carrying a different checklist for each room type.
Memento: the problem. You want undo, checkpoints or a draft you can roll back. Copying an object's private fields from outside breaks encapsulation, and exposing them for the sake of undo makes every class fragile. Memento keeps the details private while still letting state be saved and restored.
Memento: the roles. The originator (the editor, the game) creates a memento that holds a copy of its state and can restore itself from one. The caretaker (the undo stack) keeps mementos and never looks inside them. Only the originator understands the contents, so its internals can change without breaking the caretaker.
class Editor:
def __init__(self):
self._text = ''
def type(self, s):
self._text += s
def save(self): # the memento: an opaque, immutable snapshot
return (self._text,)
def restore(self, memento):
(self._text,) = memento
def __str__(self):
return self._text
editor, history = Editor(), []
editor.type('Hello')
history.append(editor.save())
editor.type(', world')
history.append(editor.save())
editor.type('!!!')
editor.restore(history.pop()) # undo the exclamation marks
print(editor) # Hello, world
editor.restore(history.pop())
print(editor) # HelloMemento: costs and variants. Storing a full copy on every change uses memory, so real editors cap the history, snapshot every few steps, or store only the difference. If an undo must reverse an action rather than restore state, the Command pattern with an inverse operation is often lighter. Mementos also fit database-style checkpoints and transaction rollbacks.
Visitor: the problem. You have a family of node classes, such as the nodes of an expression tree (numbers, additions, multiplications), and you want many operations over them: evaluate, print, simplify, type-check. Adding each operation as a method on every class spreads one concern across many files and keeps changing them.
Visitor: double dispatch. Each node has one method, accept(visitor), that calls the visitor method for its own type (visitor.visit_add(self)). Which code runs depends on two things: the node's type and the visitor's type, which is double dispatch. A new operation is a new visitor class; no node class changes.
class Num:
def __init__(self, value): self.value = value
def accept(self, v): return v.visit_num(self)
class Add:
def __init__(self, left, right): self.left, self.right = left, right
def accept(self, v): return v.visit_add(self)
class Evaluate:
def visit_num(self, n): return n.value
def visit_add(self, a): return a.left.accept(self) + a.right.accept(self)
class Render:
def visit_num(self, n): return str(n.value)
def visit_add(self, a): return '(' + a.left.accept(self) + ' + ' + a.right.accept(self) + ')'
tree = Add(Num(2), Add(Num(3), Num(4)))
print(tree.accept(Evaluate())) # 9
print(tree.accept(Render())) # (2 + (3 + 4))Visitor: when it fits. It is a good fit when the set of node types is stable and the operations keep growing, as in compilers, document converters and report builders. It is a bad fit when you add node types often, because every visitor must gain a method for each new type. In Python, functools.singledispatch or structural pattern matching can often do the same job with less ceremony.
Telling them apart. Memento is about state over time: capture now, restore later. Visitor is about behavior over structure: many operations across many types. Both exist to keep one class from carrying responsibilities that do not belong to it.
- Memento saves state in an opaque snapshot so the originator can restore it without exposing its fields.
- The caretaker stores mementos but never reads them; only the originator understands them.
- Visitor adds operations to a class hierarchy without changing the classes, using accept and visit.
- Double dispatch chooses the code by both the node type and the visitor type.
- Visitor suits stable types with growing operations; adding types means editing every visitor.
Curated Curation & Deep Insights
ScaleDojo CertifiedOur system architects are vetting high-quality, authorized video guides for Memento and Visitor: Snapshots and Operations Over a Hierarchy with zero third-party platform links.
We are preparing premium, zero-competitor deep-dives for Memento and Visitor: Snapshots and Operations Over a Hierarchy. Authorized reading references will appear automatically.