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_Pattern

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;
    }
}

Implementation of Memento Design Pattern 1

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();
    }
}

Implementation of Memento Design Pattern 2

CareTaker.java

import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
 
public class CareTaker {
    private int counter;
    private Map<Integer, Memento> mementoMap 
        = new HashMap<Integer, Memento>();
 
    public CareTaker() {
        counter = 1;      
    }
    
    public void addState(Memento m){
        mementoList.put(counter, m);
        counter++;
    }
     
    public void removeState(int i) {
     mementoMap.remove(i);
    }
     
    public void printAllSavedState() {
     System.out.println("------ Saved States------");
     for(Entry<Integer, Memento> entry : mementoMap.entrySet()){
         System.out.println("State " + entry.getKey()); 
         entry.getValue().printMemento();      
     }
     System.out.println("-------------------------");
    }
 
    public Memento getState(int i){
        return mementoMap.get(i);
    }
}

Implementation of Memento Design Pattern 3

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]