memento pattern

MEMENTO DESIGN PATTERN

The word ‘memento’ refers to an object kept as a reminder or souvenir of a person or event. Memento pattern is a behavioral pattern in GoF because it captures and externalize an object’s internal state so that the object can be restored to this state at a later time.

source: GoF

OVERVIEW

Memento, the class that represents a snapshot, simply contains the state of an object to be restored to an Originator. You and get and set state that a Memento encapsulates inside.

Originator, the class in which the current state is held. Originator has a member function that creates and return a Memento with the current state of the Originator stored into the Memento. Originator also has a member function that sets its current state with the state of a given Memento object. In other words, it can create snapshot (Memento), or restore the state to the given snapshot (Memento).

Caretaker object keeps and holds the Mementos, but never modify the Mementos. Caretaker class is responsible for the memento’s safekeeping. Usually, Caretaker encapsulates a list of Mementos that you can add more to the list, or get a Memento from the list.

MEMENTO CODE EXAMPLE

Memento class:

public class Memento {
private String state;

public Memento(String state){
this.state = state;
}

public String getState(){
return state;
}
}

Originator class:

public class Originator {
private String state;

public void setState(String state){
this.state = state;
}

public String getState(){
return state;
}

public Memento createMemento(){           // return a current snapshot
return new Memento(state);
}

public void setMemento(Memento Memento){  // restore from a snapshot
state = Memento.getState();
}
}

Caretaker class:

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

main():

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.createMemento());

originator.setState(“State #3”);
caretaker.add(originator.createMemento());

originator.setState(“State #4”);
System.out.println(“Current State: ” + originator.getState());

originator.setState(caretaker.get(0));
System.out.println(“First saved State: ” + originator.getState());
originator.setState(caretaker.get(1));
System.out.println(“Second saved State: ” + originator.getState());
}
}

Output:

Current State: State #4
First saved State: State #2
Second saved State: State #3

WHEN TO USE MEMENTO

  • Need an undo and restore mechanism.
  • Database rollback. To be able to rollback, have the Originator create a snapshot (memento) before performing an operation and thus in case of failure, the memento object would be used to restore the Originator to its previous state.
  • Want to simplify Originator code so it does not need to keep track of its previous state by moving such responsibility to the Caretaker code.

COMPARISON

memento vs command

  • Both can act as magic tokens to be passed around and invoked at a later time.
  • ​In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time.
  • Both can support muti-level undos.
  • Memento pattern’s capturing and restoring object state is more expensive then Command patterns for Undo/Redo functionality.

Leave a Reply