Le patron mémento est un patron de conception logiciel qui permet de restaurer un état précédent d'un objet (retour arrière) sans violer le principe d'encapsulation.
Le mémento est utilisé par deux objets : le créateur et le gardien. Le créateur est un objet ayant un état interne (état à sauvegarder). Le gardien agit sur le créateur de manière à conserver la possibilité de revenir en arrière. Pour cela, le gardien demande au créateur, lors de chaque action, un objet mémento qui sauvegarde l'état de l'objet créateur avant la modification.
Afin de ne pas casser le principe d'encapsulation, l'objet mémento est opaque (le gardien ne peut, ou ne devrait pas, le modifier). Lors de l'utilisation de ce patron, une attention toute particulière doit être prise afin de vérifier si le créateur modifie d'autres objets ou ressources : le patron mémento doit opérer sur un seul objet.
Des exemples classiques du patron mémento incluent le générateur de nombres pseudo-aléatoires, la machine à états finis, la fonction « annulation ».
Cet exemple programmé en Java illustre l'usage du patron de conception mémento pour réaliser une commande de type annuler.
import java.util.*;
class Originator {
private String state;
public void set(String state) {
System.out.println("Originator: etat affecte a: "+state);
this.state = state;
}
public Object saveToMemento() {
System.out.println("Originator: sauvegarde dans le memento.");
return new Memento(state);
}
public void restoreFromMemento(Object m) {
if (m instanceof Memento) {
Memento memento = (Memento)m;
state = memento.getSavedState();
System.out.println("Originator: Etat après restauration: "+state);
}
}
private static class Memento {
private String state;
public Memento(String stateToSave) { state = stateToSave; }
public String getSavedState() { return state; }
}
}
class Caretaker {
private ArrayList savedStates = new ArrayList();
public void addMemento(Object m) { savedStates.add(m); }
public Object getMemento(int index) { return savedStates.get(index); }
}
class MementoExample {
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) );
}
}
Le résultat est :
Originator: etat affecte a: State1 Originator: etat affecte a: State2 Originator: sauvegarde dans le memento. Originator: etat affecte a: State3 Originator: sauvegarde dans le memento. Originator: etat affecte a: State4 Originator: État après restauration: State3