Memento Design Pattern

The Memento Design Pattern is used to store the internal state of an object so that it can be used later to restore the object back to historical state when needed. It uses a Memento object to store it's state. The state information in the memento object is not accessible form outside of the object and thus honors encapsulation. This protects the integrity of the saved state data.

The Memento design pattern evolves three actors

  • Originator : The object whose state we want to save for future use. It creates memento object capturing its internal state. It also uses previously saved memento to restore to its previous state.
  • CareTaker : The object which maintains the history of the states of Originator. It provides the data store for saving and restoring internal states. It cannot read or change the data of a memento object.
  • Memento : It is used to store the internal states of Originator at any moment of time. It is created and retrieved by the Originator and stored and maintained by Caretaker.
The Originator will store the state information in the Memento object and pass it to a CareTaker for storing it and retrieve old state information when it needs to rollback.

Advantages of Memento Pattern

  • It stores the objects state without compromising encapsulation.
  • Provides a recovery mechanism in case of failures.
  • It provides a way to maintain history of an object's life cycle.

When we should use Memento Pattern

  • When we want to restore back an abject to its previous state. It is used heavily in GUI applications for doing undo and rollback operations.
  • To maintain the atomicity of a database transaction. If a transaction failed in intermediate steps then we have to rollback all the operations performed by the transaction handler till now.
  • When we want to maintain a history of states of an object.
  • When we don’t want to expose the internal state of an object.

Implementation of Memento Design Pattern

Memento.java
public class Memento {
    private double temperature;
    private double pressure;
    private double volume;

    public Memento(double temp, double pressure, double volume){
        this.temperature = temp;
        this.pressure = pressure;
        this.volume = volume;
    }

    public double getTemperature(){
        return temperature;
    }
 
    public void printMemento(){
        System.out.println("State : [ Temperature = " + temperature
            + ", Pressure = " + pressure + ", Volume = " + volume + "]"); 
    }
 
    public double getPressure(){
 return pressure;
    }
 
    public double getVolume() {
 return volume;
    }
}

Originator.java
public class Originator {
    /*
     * Temperature, Pressure and Volume defines 
     * the state of a system under observation 
     */
    private double temperature;
    private double pressure;
    private double volume;

    public void setState(double temp, double pressure, double volume){
        this.temperature = temp;
        this.pressure = pressure;
        this.volume = volume;
    }
    
    public void printState(){
        System.out.println("State : [ Temperature = " + temperature
            + ", Pressure = " + pressure + ", Volume = " + volume + "]"); 
    }
 
    public Memento saveToMemento(){
        return new Memento(temperature, pressure, volume);
    }

    public void restoreStateFromMemento(Memento m){
        this.temperature = m.getTemperature();
        this.pressure = m.getPressure();
        this.volume = m.getVolume();
    }
}

CareTaker.java
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;

public class CareTaker {
    private int counter;
    private Map mementoList 
        = new HashMap();

    public CareTaker() {
        counter = 1;      
    }
   
    public void addState(Memento m){
        mementoList.put(counter, m);
        counter++;
    }
    
    public void removeState(int i) {
     mementoList.remove(i);
    }
    
    public void printAllSavedState() {
     System.out.println("------ Saved States------");
     for(Entry entry : mementoList.entrySet()){
         System.out.println("State " + entry.getKey()); 
         entry.getValue().printMemento();      
     }
     System.out.println("-------------------------");
    }

    public Memento getState(int i){
        return mementoList.get(i);
    }
}

MementoPatternExample.java
public class MementoPatternExample{
    public static void main(String args[]){
 Originator originator = new Originator();
 CareTaker careTaker = new CareTaker();
 // Set initial state of system
 originator.setState(10.5, 5.4, 100.3);
 // Save initial state of system
 careTaker.addState(originator.saveToMemento());
  
 // Change state of system 
 originator.setState(15.5, 3.1, 105.1);
 originator.setState(6.2, 8.3, 99.9);
 originator.setState(8.4, 7.2, 111.0);
  
 // Second Check point, Save state of system again 
 careTaker.addState(originator.saveToMemento());
  
 // Change state of system 
 originator.setState(12.5, 2.2, 123.4);
 // Print all saved states of syystem
 careTaker.printAllSavedState();
  
 // Printing current state of system 
     System.out.println("------ Current State------");
 originator.printState();
 // Restore state of system to initial state
 originator.restoreStateFromMemento(careTaker.getState(1));
 // Printing current state of system after restoring 
     System.out.println("------ State after Restoration------");
 originator.printState();
    }
}

Output

 ------ Saved States------
State 1
State : [ Temperature = 10.5, Pressure = 5.4, Volume = 100.3]
State 2
State : [ Temperature = 8.4, Pressure = 7.2, Volume = 111.0]
-------------------------
------ Current State------
State : [ Temperature = 12.5, Pressure = 2.2, Volume = 123.4]
------ State after Restoration------
State : [ Temperature = 10.5, Pressure = 5.4, Volume = 100.3]

Related Topics
Bridge Design Pattern
Facade Design Pattern
Interpreter Design Pattern
Factory Design Pattern
Abstract Factory Design Pattern
Singleton Design Pattern
Filter Design Pattern
Composite Design Pattern
State Design Pattern
Observer Design Pattern
List of Design Patterns