Memento

Lets you save and restore the previous state of an object without revealing the details of its implementation.

classDiagram
    class Originator {
        -state
        +save() Memento
        +restore(Memento)
    }
    class Memento {
        -state
        -Memento(state)
        +getState()
    }
    class Caretaker {
        -Memento[] history
        +doSomething()
        +undo()
    }

    Originator ..> Memento
    Caretaker o-- Memento

When to use

Use the Memento pattern when you want to produce snapshots of the object’s state to be able to restore a previous state of the object. Use when direct access to the object’s fields/getters/setters violates its encapsulation.

Explanation

Problem

Imagine that you’re creating a text editor app. In addition to simple text editing, your editor can format text, insert inline images, etc. You decided to let users undo any operations carried out on the text.

You chose to record the state of all objects before performing any operation. Later, when a user decides to revert an action, you fetch the latest snapshot from the history and restore the state of all objects.

The problem is that you have to expose all internal details of classes to make them copyable. But this makes the code fragile.

Solution

The Memento pattern delegates creating the state snapshots to the actual owner of that state, the originator object. Instead of other objects trying to copy the editor’s state from the “outside,” the editor class itself can make the snapshot since it has full access to its own data.

The snapshot is a special object called memento. The contents of the memento are not accessible to any other object except the one that produced it. Other objects must communicate with mementos using a limited interface which may allow fetching the snapshot’s metadata (creation time, name, etc.), but not the original object’s state contained in the snapshot.

Real world problem

  1. Text Editors: Undo/Redo functionality.
  2. Game Saves: Saving the game state (level, health, inventory).
  3. Transactions: Database transactions rollback mechanism.

Pros and Cons

Pros Cons
- Encapsulation: You can produce snapshots of the object’s state without violating its encapsulation.
- Simplification: You can simplify the originator’s code by letting the caretaker maintain the history of the originator’s state.
- RAM: The app might consume lots of RAM if clients create mementos too often.
- Dynamic State: Caretakers need to track the originator’s lifecycle to be able to destroy obsolete mementos.

Comparison

  • Command: Memento works with Command to implement Undo.
  • Prototype: Prototype saves state by cloning efficiently. Memento saves state to a data object.
  • Iterator: You can use Memento to capture the current iteration state.

Code example

Typescript

Php