What if you could rewind your app's state like a video, without messy code or bugs?
Why Memento pattern in LLD? - Purpose & Use Cases
Start learning this pattern below
Jump into concepts and practice - no test required
Imagine you are writing a drawing app where users can undo and redo their actions. Without a system to save states, you try to manually track every change by copying the entire drawing each time. This quickly becomes confusing and slow.
Manually saving every change means lots of repeated code and high memory use. It's easy to forget to save a state or restore it incorrectly, causing bugs. Undo and redo become unreliable and hard to maintain.
The Memento pattern lets you save an object's state safely without exposing its details. You can store snapshots and restore them later, making undo/redo simple, clean, and reliable.
saveState() { this.saved = JSON.stringify(this.data); }
restoreState() { this.data = JSON.parse(this.saved); }createMemento() { return new Memento(this.data); }
restore(memento) { this.data = memento.getState(); }It enables easy and safe state rollback, making features like undo, redo, and checkpoints possible without messy code.
Text editors use the Memento pattern to let you undo typing mistakes by restoring previous document states seamlessly.
Manually tracking state changes is error-prone and inefficient.
Memento pattern cleanly separates state saving and restoring.
It simplifies undo/redo and improves code maintainability.
Practice
Memento pattern in system design?Solution
Step 1: Understand the role of Memento pattern
The Memento pattern is designed to capture and externalize an object's internal state so that it can be restored later without exposing the object's implementation details.Step 2: Compare with other design patterns
Other options describe different patterns: A is about object creation (Factory), C is about synchronization (Mutex), D is about interface compatibility (Adapter).Final Answer:
To save and restore an object's state without exposing its internal details -> Option DQuick Check:
Memento = Save & Restore State [OK]
- Confusing Memento with Factory or Adapter patterns
- Thinking it manages concurrency
- Assuming it changes object interfaces
Solution
Step 1: Identify components of Memento pattern
The Memento pattern consists of three main parts: Originator (the object whose state is saved), Memento (the object storing the state), and Caretaker (manages mementos).Step 2: Eliminate other patterns
Options B, C, and D correspond to Observer, Proxy, and Decorator patterns respectively, which are unrelated to Memento.Final Answer:
Originator, Memento, Caretaker -> Option BQuick Check:
Components = Originator + Memento + Caretaker [OK]
- Mixing Memento components with Observer or Proxy
- Forgetting the Caretaker role
- Confusing Memento with Decorator pattern
class Memento:
def __init__(self, state):
self._state = state
class Originator:
def __init__(self):
self._state = ""
def set_state(self, state):
self._state = state
def save(self):
return Memento(self._state)
def restore(self, memento):
self._state = memento._state
originator = Originator()
originator.set_state("State1")
memento = originator.save()
originator.set_state("State2")
originator.restore(memento)
print(originator._state)What will be printed?
Solution
Step 1: Trace state changes in Originator
Initially, Originator's state is set to "State1". Then a Memento is saved capturing "State1". Next, state changes to "State2".Step 2: Restore state from Memento
Calling restore with the saved Memento sets the state back to "State1". The print statement outputs the restored state.Final Answer:
State1 -> Option CQuick Check:
Restore resets state to saved value [OK]
- Assuming print shows latest state before restore
- Confusing save and restore methods
- Expecting error due to private variable access
class Originator:
def __init__(self):
self._state = ""
def set_state(self, state):
self._state = state
def save(self):
return self._state # returns state directly
def restore(self, memento):
self._state = memento
originator = Originator()
originator.set_state("State1")
memento = originator.save()
originator.set_state("State2")
originator.restore(memento)
print(originator._state)Solution
Step 1: Analyze the save method
The save method returns the internal state directly instead of encapsulating it in a Memento object, exposing internal details.Step 2: Understand Memento pattern principle
The pattern requires hiding the internal state inside a Memento object to prevent external access. Returning raw state breaks encapsulation.Final Answer:
The save method returns state directly, exposing internal details -> Option AQuick Check:
Save must hide state in Memento [OK]
- Thinking restore method is faulty
- Believing Memento class is mandatory in code
- Ignoring encapsulation principle
Solution
Step 1: Consider memory and undo tradeoff
Storing a Memento after every character change (Store a Memento after every single character change) uses excessive memory and is inefficient.Step 2: Evaluate checkpoint strategy
Storing Mementos after significant changes or checkpoints (Store a Memento only after significant changes or at checkpoints) reduces memory use while allowing meaningful undo steps.Step 3: Assess other options
Store all changes as raw text snapshots without Memento objects wastes memory by storing raw snapshots without encapsulation; Do not store any state; rely on user to retype removes undo capability.Final Answer:
Store a Memento only after significant changes or at checkpoints -> Option AQuick Check:
Checkpoint Mementos balance memory and undo [OK]
- Saving state too frequently causing memory bloat
- Ignoring encapsulation by storing raw snapshots
- Not implementing undo at all
