Monday 13 April 2015

Memento Design Pattern Implementation

Memento Design Pattern


Question:- What is Memento Design Pattern?

Answer:-This design pattern also falls under Behavioral design pattern. This(Mediator) pattern is used When we want to persist an object state so that in future we can restore to its previous state easily.
The participants which involves in this design pattern are :
  • Memento: This is the basic object that is stored in different states.
  • Originator: This sets and gets the values from the currently targeted Memento and also Creates new Mementos and assigns current values to them.
  • Caretaker: This helps to hold a List of all previous versions of the Mementos. It can store and retrieve stored Mementos. It acts like a repository and does not make changes to mementos


As per GOF :- “Captures and externalizes an object's internal state so that it can be restored later, all without violating encapsulation.”

Question:- When to use Memento design pattern?
Answer:- If we want to restore an object into a state that existed previously include: saving and restoring. For example the state of a player in a computer game or the implementation of an undo operation in a database like in any text editor.

Advantage of Memento Pattern:
  • It helps to keep the saved state external from key object which helps to maintain cohesion.
  • It keeps the key object's data encapsulated.
  • This design pattern provides easy-to-implement recovery capability.

Memento design pattern in Real world :- We have seen option in cellphone i.e. Restore phone data with factory settings

Other example :- Undo or backspace or ctrl+z is one of the most used operation in an editor. Memento design pattern is used to implement the undo operation.

b) Memento design pattern in Java :-
java.util.Date (the setter methods do that, Date is internally represented by a long value)
All implementations of java.io.Serializable
All implementations of javax.faces.component.StateHolder

We will see the implementation of this design pattern in the below example.
package com.gaurav.designpattern.memento;

Memento.java
/**
 * @author Gaurav
 *
 */
public class Memento {
private String objectState;

public Memento(String stateToSave) {
objectState = stateToSave;
}

public String retrieveSavedState() {
return objectState;
}
}

Originator.java

package com.gaurav.designpattern.memento;

/**
 * @author Gaurav
 *
 */
public class Originator {
private String objectState;

public void set(String state) {
System.out.println("Inside Originator, setting state to :- " + state);
this.objectState = state;
}

public Memento saveToMemento() {
System.out.println("Inside Originator saving the object state to Memento.");
return new Memento(objectState);
}

public void restoreFromMemento(Memento memento) {
objectState = memento.retrieveSavedState();
System.out.println("Inside Originator, object state after restoring from Memento :- "
+ objectState);
}
}


Caretaker.java


package com.gaurav.designpattern.memento;

/**
 * @author Gaurav
 *
 */
import java.util.ArrayList;
import java.util.List;

public class Caretaker {
private List<Memento> objSavedStates = new ArrayList<Memento>();

public void saveToMemento(Memento memento) {
objSavedStates.add(memento);
}

public Memento getFromMemento(int index) {
return objSavedStates.get(index);
}
}

MementoDesignPatternDemo.java

package com.gaurav.designpattern.memento;

/**
 * @author Gaurav
 *
 */
public class MementoDesignPatternDemo{
public static void main(String[] args) {
Originator originator = new Originator();
originator.set("Data State 1");
originator.set("Data State 2");
Caretaker caretaker = new Caretaker();
caretaker.saveToMemento(originator.saveToMemento());
originator.set("Data State 3");
caretaker.saveToMemento(originator.saveToMemento());
originator.set("Data State 4");
originator.restoreFromMemento(caretaker.getFromMemento(1));
}
}

Result:-

Inside Originator, setting state to :- Data State 1
Inside Originator, setting state to :- Data State 2
Inside Originator saving the object state to Memento.
Inside Originator, setting state to :- Data State 3
Inside Originator saving the object state to Memento.
Inside Originator, setting state to :- Data State 4
Inside Originator, object state after restoring from Memento :- Data State 3