tl  tr
  Home | Tutorials | Articles | Videos | Products | Tools | Search
Interviews | Open Source | Tag Cloud | Follow Us | Bookmark | Contact   
 Design Patterns > Java Design Patterns > Memento

Memento 

Memento comes under Behavioral design pattern. It provides a way to capture the internal state of an object and restore the object to its previous state at some point later just like undo operation.

Behaviour & Advantages

  • Captures the snapshot state of an object.
  • Restores object to its previous state from one of the available snapshot states.
  • Memento
    It stores the internal state of Originator. Shouldn't allow any other object to modify saved state. Originator may sign the Memento for verification during restore.
  • Originator
    It creates a Memento by saving its internal state. Uses the same Memento for restore at later point.
  • Caretaker
    It keeps track of Mementos until its required during restore. Caretaker shouldn't modify the saved state of Memento.

Check the createMemento method of Originator which saves the internal state of Originator to a newly created memento and seals the object with its signature. In restoreMemento method the signature set to memento is verified before restoring Originator state. Originator implementation is shown below,

File Name  :  
com/bethecoder/tutorials/dp/memento/Originator.java 
   
package com.bethecoder.tutorials.dp.memento;

public class Originator {

  private String state;
  private String signature;
  
  public void setState(String state) {
    this.state = state;
  }
  
  public Memento createMemento() {
    /**
     * Create a Memento and mark the signature.
     */
    Memento memento  = new Memento(state);
    memento.setSignature(getSignature());
    return memento;
  }
  
  public void restoreMemento(Memento memento) {
    /**
     * Verify the Memento signature set previously.
     */
    if (getSignature().equals(memento.getSignature())) {
      this.state = memento.getState();
    else {
      throw new IllegalArgumentException("Invalid memento : " + memento);
    }
  }

  /**
   * Generate unique signature for this instance of Originator.
   */
  private String getSignature() {
    if (signature == null) {
      signature = "Originator@" 
              System.currentTimeMillis() 
                "@" (Math.random() 1729);
    }
    return signature;
  }
  
  public String toString() {
    return "Originator[" + state + "]";
  }
  
  /**
   * Don't let others modify the 'Memento'
   * except the Originator that produced it.
   */
  public static class Memento {

    private String state;
    private String signature;
    
    private Memento(String state) {
      this.state = state;
    }

    private String getState() {
      return state;
    }

    private String getSignature() {
      return signature;
    }

    private void setSignature(String signature) {
      this.signature = signature;
    }
  }
}
   

The saveState method of Caretaker requests a memento from Originator and queues it for later restore. The restoreState method restores the Originator to its most recently saved state. Caretaker implementation is shown below,

File Name  :  
com/bethecoder/tutorials/dp/memento/Caretaker.java 
   
package com.bethecoder.tutorials.dp.memento;

import java.util.ArrayList;
import java.util.List;

public class Caretaker {

  private Originator originator = null;
  private List<Originator.Memento> savedStates = 
          new ArrayList<Originator.Memento>();

  public Caretaker(Originator originator) {
    this.originator = originator;
  }
  
  public synchronized void saveState() {
    savedStates.add(originator.createMemento());
  }
  
  public synchronized void restoreState() {
    if (savedStates.size() 0) {
      originator.restoreMemento(
          savedStates.remove(savedStates.size()-1));
    }
  }
  
  public Originator getoriginator() {
    return originator;
  }
}
   

Memento usage is shown below,

File Name  :  
com/bethecoder/tutorials/dp/memento/Test.java 
   
package com.bethecoder.tutorials.dp.memento;

public class Test {

  /**
   @param args
   */
  public static void main(String[] args) {
    
    Originator originator = new Originator();
    Caretaker caretaker = new Caretaker(originator);
    
    /**
     * Save state
     */
    originator.setState("SERVER_STARTING");
    System.out.println("Current State : " + originator);
    caretaker.saveState();
    
    originator.setState("SERVER_RUNNING");
    System.out.println("Current State : " + originator);
    caretaker.saveState();
    
    originator.setState("SERVER_ABOUT_TO_STOP");
    System.out.println("Current State : " + originator);
    caretaker.saveState();
    
    originator.setState("SERVER_STOPPED");
    System.out.println("Current State : " + originator);
    caretaker.saveState();
    
    
    System.out.println();
    
    /**
     * Restore state
     */
    caretaker.restoreState();
    System.out.println("Restored State : " + originator);
    
    caretaker.restoreState();
    System.out.println("Restored State : " + originator);
    
    caretaker.restoreState();
    System.out.println("Restored State : " + originator);
    
    caretaker.restoreState();
    System.out.println("Restored State : " + originator);
  }

}
   

It gives the following output,
Current State : Originator[SERVER_STARTING]
Current State : Originator[SERVER_RUNNING]
Current State : Originator[SERVER_ABOUT_TO_STOP]
Current State : Originator[SERVER_STOPPED]

Restored State : Originator[SERVER_STOPPED]
Restored State : Originator[SERVER_ABOUT_TO_STOP]
Restored State : Originator[SERVER_RUNNING]
Restored State : Originator[SERVER_STARTING]



 
  


  
bl  br