Memento

La programmation avec design patterns

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com
Le rollback est une notion qui au premier regard semble liée uniquement à des bases de données. Cependant, les langages de programmation peuvent en avoir aussi besoin. C'est le cas avec l'utilisation d'un design pattern appelé memento.

A travers cet article on verra le nouveau patron de conception, memento (mémento). Son objectif est le même que la commande rollback lors d'une opération SQL. Il permet d'annuler les modifications effectuées sur un élément ou même revenir à un état précis de l'objet. Mémento appartient à la famille des patrons de conceptions comportementaux.

Trois acteurs participent dans mémento :
- memento (mémento) : mémento est un objet qui stocke les informations sur l'état envoyées par l'originator.
- originator (créateur) : un objet qui contient le mémento dans son état le plus actuel. Il permet également de restaurer mémento à partir d'un moment précis du passé. Idéalement, c'est uniquement lui qui pourra accéder à l'état interne du mémento.
- caretaker (concierge) : c'est l'objet qui stocke toutes les représentantions du mémento. Contrairement au créateur, le concierge est une sorte de conteneur qui stocke toute historique d'activités liées à un objet. Il ne permet pas d'accéder à une propriété du mémento.

On peut penser que ce design pattern se base sur les copies des objets sauvegardées dans un certain point dans le temps. Cependant, ce n'est pas le cas. Notre application ne sauvegarde pas un état, mais crée de nouveaux objets. Comme on peut supposer, ces objets s'appellent bel et bien mémentos. Ils sont donc des objets à plein peau qui stockent un état donné avec d'autres informations obligatoires. Il faut seulement éviter de ne pas stocker trop d'attributs gourmands car cela peut avoir des effes neffastes sur le fonctionnement du système.

Dans le monde réel on ne peut pas revenir dans le passé. C'est pourquoi l'utilisation du mémento est impossible à trouver. Pour ce faire, on doit se faire aider par un peu d'imagination. Chaque personnes grandit chaque année. Cela signifie qu'on a tous un an de plus. Maintenant si l'on voudrait utiliser mémento, on nous souvegarderait à un certain âge, une fois par l'année. Avec une machine de retour au passé, on pourrait alors très facilement revenir à un certain âge pour, par exemple, réparer les erreurs ou tout simplement mieux passer le bac.

Exemple du mémento
L'exemple du mémento sera un objet qui contient un état (State). Pour la facilité de compréhension, les objets auront exactement les mêmes noms que les acteurs mentionnés précédemment dans l'article.


class Originator {
private State state;
private String firstName;
private String familyName;

public Originator(String firstName, String familyName) {
this.firstName = firstName;
this.familyName = familyName;
}

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

public State getState() {
return this.state;
}

public Memento saveState() {
return new Memento(state);
}

public void getToThePast(Memento memento) {
this.state = memento.getState();
}

}

Ci-dessus notre auteur qui initialise les objets à mémoriser, mais aussi qui permet de récupérer l'objet mémorisé à un état inférieur. L'auteur est en fait une personne qui, au cours de sa vie, peut changer les noms de famille (suite par exemple à un mariage ou à un divorce).


class Memento {
private State state;

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

public State getState() {
return this.state;
}

}

La classe Memento est celle qu'on souhaite sauvegarder. On voit que ce qui nous intéresse, c'est uniquement l'état (State) et non pas les attributs nom et prénom de la classe Originator. On suppose que les deux attributs sont une sorte d'identifiant qui ne change pas à travers les années. Leur stockage est alors peu utile.


class Caretaker {
private List<Memento> states;

public Caretaker() {
this.states = new ArrayList<Memento>();
}

public void addMemento(Memento memento) {
this.states.add(memento);
}

public Memento restoreState(int index) {
return this.states.get(index);
}


}

Cette classe stocke tous les objets mémento. Elle permet aussi bien de rajouter un nouvel objet que de restaurer un ancien.



class State {
private String name;
private String yearFrom;
private String yearTo;

public State(String name, String yearFrom, String yearTo) {
this.name = name;
this.yearFrom = yearFrom;
this.yearTo = yearTo;
}

@Override
public String toString() {
return "Stage of life " + this.name + " was between " + this.yearFrom + " and " + this.yearTo;
}
}

La classe State représente l'état sauvegardé par l'instance Memento. On voit la présence des 3 attributs : l'étape d'une vie et les années de cette étape. On verra cela plus clairement plus bas, dans le code du client :


Caretaker caretaker = new Caretaker();

Originator person = new Originator("Sylvie", "Beaucoeur");
person.setState(new State("childhood", "1989", "1996"));
caretaker.addMemento(person.saveState());

person.setState(new State("teens", "1996", "2006"));
caretaker.addMemento(person.saveState());

person.setState(new State("maturity", "2006", "2013"));
caretaker.addMemento(person.saveState());

person.getToThePast(caretaker.restoreState(0));
System.out.println("The first etape of her life was : "+person.getState());


Le code sortira le texte suivant :

The first etape of her life was : Stage of life childhood was between 1989 and 1996


Dans cet article on a vu comment manipuler l'objet et tous ses états avec le design pattern memento. Grâce à un créateur et un objet "intermédiaire", mémento, on peut très rapidement restaurer l'objet à son état inférieur. Cela peut être utile dans toutes les fonctions du type rollback, comme par exemple annulation d'un changement.
Bartosz KONIECZNY 27-11-2013 06:18 design patterns
Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil Android

Un problème de connexion à un web service ou à l'internet.

Vérifiez dans votre AndroidManifest.xml si la balise suivante est présente :
<uses-permission android:name="android.permission.INTERNET" />