Nov
2
Behavioral Design Pattern: The Memento
During the courses that I have followed on The Hague University of Applied Sciences, Design Patterns have lead a dominant role in many of the projects that I have completed. Design Patterns are tested solutions to common problems, and the beauty of these patterns is that they are extendable, maintainable and re- useable. In an effort to better understand the different Design Patterns that exist today, I’ve started a series of blogs that elaborate on the different patterns. This is mostly to support my studying, since I would be putting my knowledge into words, which helps me to learn and understand. However, I am more than happy to share my findings with whomever is interested. Every Pattern will be supported with code examples, mostly done in Java. You don’t need to be a Java master, but it is handy to know about OOP programming and Java in general.
In this article, we’re going to take a closer look at the Memento Pattern.
The Memento Design Pattern is a Behavioral Pattern. This one is extremely helpfull in giving you the means to restore an object to its previous state. The Memento works with two Objects, the Object whoms states have to be saved and the object who’ll save those states. Each time certain changes are made to the “Originator”(The object who’s states have to be saved), a memento is created and stored in a list of states. Then, later, if a rollback has to occur, one of these mementos or states can be chosen from the list of states and then the object can be reverted to that state.
As you can see in the diagram, the Originator is the one that knows how to save himself. The caretaker is used to hold Memento objects for later use. It is used for storage purposes only; it should neither examine or modify the contents of the Memento object. The Memento itself is the saved state of the Originator. It will be passed on to the Caretaker for storage, untill it is used again.
Code Implementation
We’ll start the implementation with the Originator:
// The Originator class Originator { private String state; public void set(String state) { System.out.println("Originator: Setting state to "+state); this.state = state; } public Memento saveToMemento() { System.out.println("Originator: Saving to Memento."); return new Memento(state); } public void restoreFromMemento(Memento m) { state = m.getSavedState(); System.out.println("Originator: State after restoring from Memento: "+state); } }
The Originator knows that he wants to be saved. When his state changes, the saveToMemento() function will take care of the fact that the old state shall be saved, before the new state is implemented.
//The Memento class Memento { private String state; public Memento(String stateToSave) { state = stateToSave; } public String getSavedState() { return state; } }
The Memento is pretty straight forward. The moment you create it, you’ll have to pass the state along. You can request the saved state any time.
//The Caretaker class Caretaker {
private ArrayList<Memento> savedStates = new ArrayList<Memento>(); public void addMemento(Memento m) { savedStates.add(m); } public Memento getMemento(int index) { return savedStates.get(index); } }
And here we have our caretaker. It takes care of all the saved states that we want to save. All we have to do now, is tie this together in a neat client:
//Client public static void main(String[] args) { Caretaker caretaker = new Caretaker(); Originator originator = new Originator(); originator.set("State1"); originator.set("State2"); caretaker.addMemento( originator.saveToMemento() ); originator.set("State3"); caretaker.addMemento( originator.saveToMemento() ); originator.set("State4"); originator.restoreFromMemento( caretaker.getMemento(1) ); }
Now our story is complete. In this example you’ll see that state1 isn’t saved at all, whilst 2 and 3 are. They are passed to the caretaker, whom’ll hold on to it, and when we use the restoreFromMemento function, you’ll see that state4 is reverted to state3.
Related posts:
