Memento Pattern

Also Known as: Token

The state of an object can be defined as the values of its properties or attributes at any given point of time. The Memento pattern is useful for designing a mechanism to capture and store the state of an object so that the object can be put back to this previous state if needed; Like an undo operation. The object whose state needs to be captured is referred to as Originator. The Originator stores all those attributes that are required for restoring its state in a separate object referred to as Memento.

Memento does not expose the object’s internal structure. Memento is usually implemented as an inner class of Originator.

There is another object involved called Caretaker or Memento Handler. The Caretaker can ask the originator for a memento object and can roll back. When the client wants to restore the Originator back to its previous state, it simply passes a Memento back to the Originator using the Caretaker.

Structure

memento.jpeg

Example

class Originator {
    private Object originatorState; // the originatorState we want to keep
 
    public Memento saveToMemento() {
        // save the current originatorState to a memento
        Memento memento = new Memento();
        memento.saveState(originatorState);
        return memento;
    }
 
    public void restoreFromMemento(Memento memento) {//this is undo
        originatorState = memento.getSavedState();
    }
 
    public void setState(Object state) {
        this.originatorState = state;
    }
 
    // Does not need to be inner always
    static class Memento {
        private Object state;
 
        public void saveState(Object theState) {
            state = theState;
        }
 
        public Object getSavedState() {
            return state;
        }
    }
}
 
class CareTaker {
    private List<Memento> savedStates = new ArrayList<Memento>();//this is the undo list
 
    public void addMemento(Memento m) { savedStates.add(m); }
    public Memento getMemento(int index) { return savedStates.get(index); }
} 
 
class Client {
    public static void main(String[] args) {
        CareTaker caretaker = new CareTaker();
 
        Originator originator = new Originator();
        originator.setState("State1");
        caretaker.addMemento(originator.saveToMemento());
        originator.setState("State2"); // chaging the state of originator
        caretaker.addMemento(originator.saveToMemento());
        // putting the state back
        originator.restoreFromMemento(caretaker.getMemento(1));
    }
}

Example of Command and Memento together:

todo

Applicability

  • One way of implementing undo/redo is just to simply keep them in a list as above example.

Related Patterns

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License