Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Memento
LLD

Memento

Understand how to capture and restore an object's previous state without exposing its internal structure.

Memento: Snapshot & Restore

The Memento design pattern provides a way to save an object’s state and restore it later, while keeping the object’s internal representation encapsulated.

It is commonly used for undo/redo, checkpoints, game saves, drafts, and rollback.


1. The Problem

Consider a text editor:

TextDocument
+----------------------+
| text = "Hello"       |
| cursor = 5           |
+----------------------+

An undo manager needs to remember this state.

One approach is to expose the fields:

document.getText();
document.getCursor();

Now the undo manager knows how TextDocument is implemented.

If the document later changes internally:

Before:
text + cursor

After:
DocumentTree + Cursor + Selection + Formatting

the undo manager may also need to change.

Memento avoids this coupling.

TextDocument
     |
     | save()
     v
  Memento
     |
     | store
     v
UndoManager

The document creates its own snapshot, so it decides what needs to be saved.


2. Structure

There are three main participants.

+-------------------+
|    Originator     |
|-------------------|
| application state |
|-------------------|
| save()            |
| restore(memento)  |
+---------+---------+
          |
          | creates
          v
+-------------------+
|      Memento      |
|-------------------|
| saved state       |
+---------+---------+
          ^
          |
          | stores
+---------+---------+
|     Caretaker     |
|-------------------|
| history           |
+-------------------+

Originator

The object whose state is being saved.

Memento

The snapshot of that state.

Caretaker

Stores and manages snapshots.

The Caretaker should not need to understand the snapshot’s internal data.


3. Basic Flow

      save()
        |
        v
+-------------+       +-------------+
| Originator  | ----> |   Memento   |
+-------------+       +-------------+
                             |
                             | store
                             v
                      +-------------+
                      |  Caretaker  |
                      +-------------+

Later:

Caretaker
    |
    | retrieve
    v
 Memento
    |
    | restore
    v
Originator

The lifecycle is:

Create state

Save

Store snapshot

Change object

Retrieve snapshot

Restore

4. Java Example

class TextDocument {

    private String text = "";
    private int cursor = 0;

    void write(String value) {
        text += value;
        cursor = text.length();
    }

    Snapshot save() {
        return new Snapshot(text, cursor);
    }

    void restore(Snapshot snapshot) {
        text = snapshot.text();
        cursor = snapshot.cursor();
    }

    record Snapshot(String text, int cursor) {}
}

The history manager:

class UndoManager {

    private final Deque<TextDocument.Snapshot> history
            = new ArrayDeque<>();

    void checkpoint(TextDocument document) {
        history.push(document.save());
    }

    void undo(TextDocument document) {
        if (!history.isEmpty()) {
            document.restore(history.pop());
        }
    }
}

Usage:

TextDocument document = new TextDocument();
UndoManager undo = new UndoManager();

document.write("Hello");

undo.checkpoint(document);

document.write(" World");

undo.undo(document);

The document returns to:

"Hello"

5. Why the Memento Helps

Without Memento:

UndoManager
    |
    +-- knows text
    +-- knows cursor
    +-- knows selection
    +-- knows formatting

With Memento:

UndoManager
    |
    +-- knows only Memento

The Originator handles the details:

                 +----------------+
                 |   Originator   |
                 |----------------|
                 | knows state    |
                 | knows Memento  |
                 +----------------+
                         |
                         v
                    Memento

Caretaker
    |
    +-- stores Memento
    +-- retrieves Memento

This separation is the main reason to use the pattern.


6. What Should a Memento Contain?

Only the information required to restore the state.

For example:

Document
+----------------+
| text           | → save
| cursor         | → save
| selection      | → save
| cached wordCount| → don't need if recalculable
+----------------+

A good question is:

If I restore this Memento, can I get the Originator back to the required state?

If yes, the snapshot contains enough information.


7. Snapshot Independence

Be careful with mutable objects.

Suppose:

class Game {
    private List<String> inventory;
}

This is potentially unsafe:

return new Snapshot(inventory);

because both the current game and snapshot may reference the same list.

Game --------+
             |
             v
          List A
             ^
             |
Snapshot ----+

A later modification changes the same list.

For mutable state, an independent copy may be required:

Game -------> List A

Snapshot ---> List B

Whether a deep copy is necessary depends on the object’s state and mutability.


8. Full Snapshots vs Deltas

The simplest approach is to save the complete state.

Snapshot A = full state
Snapshot B = full state
Snapshot C = full state

This makes restoration easy but can consume significant memory.

For large states, a system may store differences:

Snapshot A
    |
   Delta B
    |
   Delta C
    |
   Delta D

Other techniques include:

TechniquePurpose
Bounded historyLimit memory usage
CoalescingCombine frequent small changes
DeltasStore only changes
Copy-on-writeShare unchanged data

For example:

100 KB snapshot × 1,000 snapshots
≈ 100 MB

So unlimited full snapshots are not always practical.


9. Undo and Redo

Memento naturally works with history.

A simple undo stack:

+-----------+
| Snapshot C| ← newest
+-----------+
| Snapshot B|
+-----------+
| Snapshot A|
+-----------+

Redo usually requires another stack:

UNDO                    REDO

+-----------+           +-----------+
| Snapshot C|           | Snapshot D|
| Snapshot B|           +-----------+
| Snapshot A|
+-----------+

The history manager is responsible for deciding how these stacks behave.


10. Memento vs Command

Both can implement undo, but they save different things.

Command:

"Insert 'Hello'"
        |
        v
Undo = perform opposite operation


Memento:

Before operation
        |
        v
Snapshot
        |
        v
After operation
        |
        v
Undo = restore snapshot
CommandMemento
StoresOperationState
UndoReverse operationRestore state
MemoryUsually smallerCan be larger
Main challengeCorrect inverseComplete snapshot
Good forStructured operationsWhole-object state

They can also be combined.


11. Memento vs Clone

They are related but have different purposes.

Clone:

Object → another copy of object

Memento:

Object → restorable representation of its state

A Memento does not necessarily have to be a complete copy of the runtime object.


12. Memento vs Serialization

Serialization can turn an object’s state into a persistent representation.

Memento is primarily about encapsulation and restoration.

They can be combined:

Originator
    |
    v
Memento
    |
    v
serialize
    |
    v
disk / database

For example, a game might create a Memento and then serialize it as a save file.


13. Internal vs External History

The Caretaker can be a separate object:

Document → Memento → UndoManager

or the Originator can manage its own history:

+----------------------+
| TextDocument         |
|----------------------|
| current state        |
| history              |
| save()               |
| restore()            |
| undo()               |
+----------------------+

A separate Caretaker is useful when history management is its own responsibility.


14. Common Real-World Uses

Memento

├── Text editor
│   └── Undo / redo

├── Drawing application
│   └── Previous canvas state

├── Games
│   └── Save games / checkpoints

├── Forms
│   └── Draft recovery

├── Configuration
│   └── Rollback

└── Workflows
    └── Checkpoints

Database savepoints and VM checkpoints use similar rollback ideas, although they are not necessarily implementations of the GoF Memento pattern.


15. Performance Considerations

The basic pattern is simple, but production systems need to consider:

Memory

How many snapshots can exist?

snapshot size × history length

Copying cost

How expensive is creating a snapshot?

Restoration cost

How quickly can the object be rebuilt?

Mutable state

Does the snapshot need deep copying?

Frequency

Should every change create a checkpoint?

Often the answer is no.

For example, an editor might combine many keystrokes into one undo operation.


16. Common Mistakes

Exposing internal state

getInternalState()

just so another class can save it.

This defeats much of the encapsulation benefit.

Letting the Caretaker inspect the snapshot

snapshot.getText();
snapshot.getCursor();

The Caretaker generally shouldn’t need to do this.

Incomplete snapshots

If important state isn’t saved, restoration is incorrect.

Shallow copying mutable state

The snapshot can accidentally change when the current object changes.

Unlimited history

Full snapshots can consume large amounts of memory.


17. When to Use Memento

Memento is a good fit when:

Need previous state?
       |
      YES
       |
       v
Need to restore it later?
       |
      YES
       |
       v
Want to keep internal representation
hidden from the state manager?
       |
      YES
       |
       v
     MEMENTO

It is especially useful when capturing the state is easier and safer than implementing inverse operations for every possible change.


18. When Not to Use It

Consider another approach when:

  • The state is extremely large.
  • Changes happen extremely frequently.
  • Every operation has a simple inverse.
  • Event history is more useful than state snapshots.
  • The object contains resources that cannot meaningfully be snapshotted, such as live connections or threads.

Possible alternatives include:

Command
Event Sourcing
Deltas
Persistent data structures
Copy-on-write
Database savepoints

My Private Notes

Notes are auto-saved locally to this device.