Memento Pattern
The Memento Pattern (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.
Introduction
Intent: Capture the internal state of an object without violating encapsulation, and save this state outside the object.
Main Solution: The Memento Pattern captures the internal state of an object without breaking encapsulation, and saves this state outside the object. This allows the object to be restored to its previously saved state later.
When to Use: Often, we need to record the internal state of an object. The purpose of doing this is to allow users to undo uncertain or incorrect operations and revert to their previous state, giving them a "second chance."
How to Solve: Use a Memento class specifically for storing the object's state.
Key Code: Clients are not coupled with the Memento class but with the Memento management class.
Application Examples: 1. "Undo" functionality.
- Save game progress.
- Windows' ctrl + z.
- Back button in Internet Explorer.
- Database transaction management.
Advantages: 1. Provides a mechanism for users to restore state, allowing them to easily return to a historical state.
- Implements information encapsulation, so users do not need to care about the details of state saving.
Disadvantages: Consumes resources. If a class has many member variables, it will inevitably occupy a large amount of resources, and each save operation will consume some memory.
Usage Scenarios: 1. Scenarios where state needs to be saved/restored.
- Providing a rollback operation.
Notes: 1. To comply with the Law of Demeter, add a class to manage the Memento.
- To save memory, use the Prototype Pattern combined with the Memento Pattern.
Implementation
The Memento Pattern uses three classes: Memento, Originator, and CareTaker. Memento contains the state of the object to be restored. Originator creates and stores the state in a Memento object. CareTaker is responsible for restoring the object's state from the Memento.
MementoPatternDemo, our demonstration class, uses CareTaker and Originator objects to show the restoration of the object's state.
Step 1
Create the 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 the 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 the 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
Use CareTaker and Originator objects.
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 the output.
Current State: State #4
First saved State: State #2
Second saved State: State #3