Memento Pattern

The Memento Pattern saves a certain state of an object so that the object can be restored at an appropriate time. The Memento Pattern is a behavioral pattern.

The Memento Pattern allows capturing and restoring an object's internal state without breaking encapsulation.

Introduction

intent

Capture an object's internal state without breaking encapsulation, and allow these states to be saved and restored outside the object.

Main problems solved

  • Allow capturing and saving an object's internal state so that it can be restored to that state in the future, enabling undo and rollback operations.

Use Case

  • When there is a need to provide an undo mechanism that allows users to roll back to previous states.

Implementation Approach

  • Create Memento classUsed to store and encapsulate the state of an object.
  • Create Originator role: Responsible for creating memento objects and restoring state as needed.
  • Create a memento management class(Optional): Responsible for managing all memento objects.

Key code

  • MementoStore the originator's state information.
  • Originator: Create memento objects and restore state based on the memento.

Application example

  • Remedy for regretProvide a function for undo operations.
  • Game Save: Save game progress and allow players to load previous save files.
  • Ctrl+Z in WindowsImplement the undo operation.
  • IE browser's Back buttonAllow users to go back to a previous page.
  • Database transaction management: Save state through transaction logs to implement rollback.

Advantages

  • Provide a state restoration mechanism: Allow users to conveniently return to historical states.
  • Encapsulate state information: Users do not need to care about the details of state saving.

Disadvantages

  • Resource Consumption: If the object's state is complex, saving state may consume significant resources.

Usage suggestions

  • Use the Memento Pattern in scenarios where data states need to be saved and restored.
  • Consider using the Prototype Pattern combined with the Memento Pattern to save memory.

Notes

  • To reduce coupling, memento objects should be managed indirectly through a memento management class.
  • The Memento Pattern should be used with caution to avoid excessive consumption of system resources.

Structure

The Memento Pattern includes the following main roles:

  • Memento: Responsible for storing the internal state of the Originator object. A memento can keep part or all of the Originator's state information.

  • Originator: Create a memento object and use it to restore the object's own internal state. The Originator usually creates a memento object when state needs to be saved, and uses the memento object when state needs to be restored.

  • Caretaker: Responsible for saving memento objects, but does not operate on or inspect them. The caretaker can only pass mementos to other objects.

Implementation

The Memento pattern uses three classesMemento、OriginatorandCareTaker. Memento contains the state of the object to be restored. Originator creates and stores the state in a Memento object. The Caretaker object is responsible for restoring the object's state from the Memento.

MementoPatternDemo, our demo class usesCareTakerandOriginatorobjects to show the restoration of object state.

备忘录模式的 UML 图

Step 1

Create Memento class.

Memento.java

public class Memento { private String state; public Memento(String state){ this.state = state; } public String getState(){ return state; } }

Step 2

Create Originator class.

Originator.java

public class Originator { private String state; public void setState(String state){ this.state = state; } public String getState(){ return state; } public Memento saveStateToMemento(){ return new Memento(state); } public void getStateFromMemento(Memento Memento){ state = Memento.getState(); } }

Step 3

Create CareTaker class.

CareTaker.java

import java.util.ArrayList; import java.util.List; public class CareTaker { private List<Memento> mementoList = new ArrayList<Memento>(); public void add(Memento state){ mementoList.add(state); } public Memento get(int index){ return mementoList.get(index); } }

Step 4

UsageCareTakerandOriginatorObject.

MementoPatternDemo.java

public class MementoPatternDemo { public static void main(String[] args) { Originator originator = new Originator(); CareTaker careTaker = new CareTaker(); originator.setState("State #1"); originator.setState("State #2"); careTaker.add(originator.saveStateToMemento()); originator.setState("State #3"); careTaker.add(originator.saveStateToMemento()); originator.setState("State #4"); System.out.println("Current State: " + originator.getState()); originator.getStateFromMemento(careTaker.get(0)); System.out.println("First saved State: " + originator.getState()); originator.getStateFromMemento(careTaker.get(1)); System.out.println("Second saved State: " + originator.getState()); } }

Step 5

Verify output.

Current State: State #4
First saved State: State #2
Second saved State: State #3
other extensions