Observateur

De Wiki L.A.B
Aller à : navigation, rechercher

Le pattern Observateur (en anglais Observer) définit une relation entre objets de type un-à-plusieurs, de façon que, si un objet change d’état, tous ceux qui en dépendent en soient informés et mis à jour automatiquement.

Pourquoi l’utiliser ?

Supposons une classe gérant des données GPS, et plusieurs classes responsables de l’affichage de ces données. On peut imaginer une méthode dans les classes d’affichages pour récupérer la position GPS, mais à quelle fréquence doivent-elles demander la position ? Chaque seconde ? Chaque milliseconde ? Avec cette solution, on ne peut pas être sûr de l’exactitude des données. La solution est d’utiliser le design pattern Observer, qui permet d’informer les classes d’affichages automatiquement lorsque la position GPS est modifiée.

Diagramme UML

Observeur UML.png


Exemple Java

Code Java

texte descriptif


2 interfaces :

/** Interface des classes que l'on veut observer **/
public interface Observable {
	public void addObserver(Observer obj);
	public void removeObserver(Observer obj);
	public void notifyObserver();
}

Une méthode pour ajouter un observeur

Une méthode pour supprimer un observeur

Une méthode pour informer tous les observeurs du changement d’état

/** 
 * Interface des classes qui vont observer
 * Correspond au différents affichages  
 * **/
public interface Observer {
	public void update (HeurePerso obj);
}

Une méthode pour traité un changement d’état (heure ou minute)

1 classe gestion de l’heure :

public class HeurePerso implements Observable{
	
	private int heure;
	private int minute;
	private ArrayList<Observer> observers;
	
	public HeurePerso() {
		super();
		this.heure = 00;
		this.minute = 00;
		this.observers = new ArrayList<Observer>();
	}

	/** Ajoute un observeur dans la liste des observers**/
	@Override
	public void addObserver(Observer obj) {
		observers.add(obj);
	}

	/** Supprime un observeur dans la liste des observers **/
	@Override
	public void removeObserver(Observer obj) {
		observers.remove(obj);
	}

	/** Informe tous les observeurs d'un changement d'état **/
	@Override
	public void notifyObserver() {
		for(int i =0; i<observers.size();i++) {
			Observer o = observers.get(i);
			o.update(this);
		}
	}
	
	public int getHeure() {
		return heure;
	}

	/** Modifie la valeur de la variable heure et informe de son changement**/
	public void setHeure(int heure) {
		this.heure = heure;
		notifyObserver();
		
	}

	public int getMinute() {
		return minute;
	}

	/** Modifie la valeur de la variable minute et informe de son changement**/
	public void setMinute(int minute) {
		this.minute = minute;
		notifyObserver();
	}

}

Classe gérant (sans affichage) l’heure

2 classe observateur :

Chaque classe affiche l’heure dans un format différent

public class AffichageFR implements Observer{

	public AffichageFR() {
		
	}

	/** Affichage de l'heure en français **/
	@Override
	public void update(HeurePerso obj) {
		System.out.println(obj.getHeure()+":"+obj.getMinute());
	}
}


public class AffichageENG implements Observer{

	public AffichageENG() {

	}

	/** Affichage de l'heure en anglais **/
	@Override
	public void update(HeurePerso obj) {
		//Si l'heure dépasse midi, on enleve 12h pour pouvoir afficher l'heure d'apres-midi (PM)
		if(obj.getHeure() >12) {
			System.out.println(obj.getHeure()-12+"."+obj.getMinute() + "PM");
		}else {
			System.out.println(obj.getHeure()+"."+obj.getMinute() + "AM");
		}
		
	}

}



Texte explicatif du code

Exemple : Affichage de l’heure Dans notre exemple, on veut gérer l’heure à partir d’une classe et l’affiché d’une ou plusieurs autres classes. On crée donc deux interface Observer et Observable. Deux Observer concret (AffichageENG et AffichageFR) implémentent l'interface Observer tandis que la classe concrète HeurePerso implémente l'interface Observable. Dans notre exemple, on créer un objet Observable «HeurePerso » que l'on nomme time. Cette classe possède une liste d'Observer, à laquelle on ajoute deux objet Observer "obsFR" et "obsENG" qu'on a créé au préalable. A chaque modification de notre objet time, il y aura un comportement différent pour chaque Observer contenu dans cette liste. Ici, dès que l'on fait appel à la fonction setHeure() ou setMinute(), cela va faire appel à la fonction notifyObserver() qui, pour chaque Observer dans la liste, appelle update(). Cette fonction update est présente dans les classe qui implémente l'interface Observable. Dans notre exemple, elle est chargée d'afficher le changement d'heure qui a eu lieu mais cette fonction peut aussi modifier, ou renvoyer, une valeur selon les cas d'utilisation. En outre, notre programme affiche l'heure soit en anglais, soit en francais. Ce design pattern permet de changer le comportement des obersavateurs sans toucher à la classe observable. La solution consiste donc à laisser la charge à la classe HeurePerso d’informer sa classe d’affichage de ses changements de valeurs. Cependant la classe HeurePerso doit pouvoir informer plusieurs classes d’affichage et cela en évitant de lier fortement les classes entre elles. C’est à dire qu’une modification des classes d’affichage ne doit pas engendrer de modification dans la classe métier et vice versa.

Désavantages

Chaque observateur souhaitant être informé d’un changement d’état doit se trouver dans le tableau d’observer de l’observable. Pour cela il faut les ajouter un par un dans ce tableau.