Divers aspects doivent être observés dans la pro­gram­ma­tion de logiciels : le produit final doit non seulement disposer des fonc­tion­na­li­tés sou­hai­tées mais également d’un code source aussi lisible et in­tel­li­gible que possible. Les efforts engagés pour y parvenir doivent être aussi faibles que possible, en par­ti­cu­lier lorsque la con­cep­tion des pro­grammes ou des parties de pro­grammes inclut des fonc­tion­na­li­tés ou des éléments ré­cur­rents. Grâce aux patrons ou modèles GoF (« Gang of Four »), les dé­ve­lop­peurs disposent d’une palette de solutions pré­dé­fi­nies visant à répondre à dif­fé­rentes pro­blé­ma­tiques de la con­cep­tion lo­gi­cielle.

En dehors des autres patrons connus tels que le patron visiteur ou le patron singleton, cette palette de patrons de con­cep­tion pratiques inclut également le patron Ob­ser­va­teur qui permet de sim­pli­fier con­si­dé­ra­ble­ment le quotidien en pro­gram­ma­tion. Nous vous ex­pli­quons ce que recouvre l’Observer design pattern (avec une re­pré­sen­ta­tion graphique en UML) et vous pré­sen­tons les atouts et les failles de ce modèle.

Qu’est-ce que l’Observer pattern (patron de con­cep­tion Ob­ser­va­teur) ?

L’Observer design pattern, abrégé en Observer pattern et traduit par « patron de con­cep­tion Ob­ser­va­teur », est l’un des modèles les plus appréciés dans la con­cep­tion de logiciels. Il fournit en effet une méthode uniforme per­met­tant de définir un rapport de dé­pen­dance entre deux objets ou plus afin de com­mu­ni­quer l’ensemble des mo­di­fi­ca­tions à un autre objet donné de façon aussi simple et rapide que possible. À cette fin, il est possible d’en­re­gis­trer n’importe quel objet comme « observer » ou ob­ser­va­teur d’un autre objet. Ce dernier objet, que l’on appelle « sujet », informe l’ob­ser­va­teur en­re­gis­tré dès qu’il a été modifié ou adapté.

Comme évoqué au­pa­ra­vant, l’Observer pattern fait partie des « modèles GoF » publiés en 1994 dans « Design Patterns: Elements of Reusable Object-Oriented Software ». La vingtaine de solutions pour la con­cep­tion lo­gi­cielle décrite dans cet ouvrage joue aujourd’hui un rôle essentiel dans la con­cep­tion et l’éla­bo­ra­tion des ap­pli­ca­tions in­for­ma­tiques.

But et fonc­tion­ne­ment de l’Observer pattern

Le patron de con­cep­tion Ob­ser­va­teur utilise deux types d’acteurs : d’une part le sujet, c’est-à-dire l’objet dont le statut doit être observé sur la durée ; d’autre part, les objets observant (observers ou ob­ser­va­teurs) qui sou­hai­tent être informés de toutes les mo­di­fi­ca­tions apportées au sujet.

Remarque
Ha­bi­tuel­le­ment, on attribue plusieurs ob­ser­va­teurs à un sujet. Toutefois, l’Observer pattern peut en principe être utilisé pour un seul objet ob­ser­va­teur.

En l’absence du patron de con­cep­tion Ob­ser­va­teur, les ob­ser­va­teurs devraient demander ré­gu­liè­re­ment au sujet des mises à jour sur son statut. Chaque requête in­di­vi­duelle im­pli­que­rait un temps de calcul cor­res­pon­dant ainsi que les res­sources ma­té­rielles né­ces­saires à cet effet. L’idée de base de l’Observer pattern est de cen­tra­li­ser la tâche d’in­for­ma­tion sur le sujet. À cette fin, il crée une liste dans laquelle les ob­ser­va­teurs peuvent s’inscrire. En cas de mo­di­fi­ca­tion, le sujet informe les ob­ser­va­teurs dans l’ordre de leur ins­crip­tion, sans que ces derniers aient besoin d’être actifs. Si on ne souhaite plus qu’un ob­ser­va­teur soit au­to­ma­ti­que­ment informé des mises à jour du statut, il suffit de le retirer de la liste.

Note
Il existe deux méthodes pour informer les dif­fé­rents ob­ser­va­teurs : dans la méthode « push », le sujet transmet le statut modifié dès la no­ti­fi­ca­tion. Ceci peut toutefois entraîner des problèmes si des in­for­ma­tions ne pouvant être ex­ploi­tées par l’ob­ser­va­teur sont trans­mises. Ce problème ne survient pas dans la méthode al­ter­na­tive que l’on appelle méthode « pull » : dans cette approche, le sujet indique uni­que­ment que des mo­di­fi­ca­tions ont été apportées. Les ob­ser­va­teurs doivent ensuite demander le statut modifié via un appel séparé.

Re­pré­sen­ta­tion graphique de l’Observer pattern (diagramme UML)

Le fonc­tion­ne­ment et l’uti­li­sa­tion des patrons de con­cep­tion tels que l’Observer pattern sont souvent dif­fi­ciles à com­prendre pour des personnes ex­té­rieures. Une re­pré­sen­ta­tion graphique de ce modèle de con­cep­tion permettra de faciliter la com­pré­hen­sion. Très répandu, le langage de mo­dé­li­sa­tion UML (Unified Modeling Language) est idéal pour cette re­pré­sen­ta­tion puisqu’il permet de présenter les liens de façon claire et com­pré­hen­sible pour les uti­li­sa­teurs et les experts en ap­pli­ca­tions. C’est la raison pour laquelle nous avons utilisé l’UML pour re­pré­sen­ter l’Observer pattern de façon abstraite.

Quels sont les avantages et les in­con­vé­nients de l’Observer design pattern ?

L’uti­li­sa­tion de l’Observer pattern dans le dé­ve­lop­pe­ment logiciel peut s’avérer avan­ta­geuse dans de nom­breuses si­tua­tions. Le principal avantage de ce concept est le haut degré d’in­dé­pen­dance entre l’objet observé (sujet) et les ob­ser­va­teurs qui s’appuient sur le statut actuel de cet objet. Par exemple, l’objet observé n’a nullement besoin de disposer d’in­for­ma­tions sur ses ob­ser­va­teurs puisque l’in­te­rac­tion peut être réalisée in­dé­pen­dam­ment via l’interface de l’ob­ser­va­teur. Les ob­ser­va­teurs reçoivent les mises à jour au­to­ma­ti­que­ment ce qui supprime to­ta­le­ment les requêtes sans résultat puisque le sujet reste le même.

Cependant, le fait que le sujet informe au­to­ma­ti­que­ment tous les ob­ser­va­teurs en­re­gis­trés des mo­di­fi­ca­tions ne présente pas que des avantages : en effet, les in­for­ma­tions sur la mo­di­fi­ca­tion sont trans­mises même si elles ne sont pas per­ti­nentes pour l’un des ob­ser­va­teurs. Cela peut se révéler pro­blé­ma­tique si le nombre d’ob­ser­va­teurs en­re­gis­trés est très important puisque le modèle Ob­ser­va­teur pourra gaspiller un temps de calcul con­si­dé­rable dans la trans­mis­sion. Un autre problème du patron de con­cep­tion Ob­ser­va­teur est que, bien souvent, le code source du sujet ne permet pas de dé­ter­mi­ner quel ob­ser­va­teur doit recevoir les in­for­ma­tions.

Observer pattern : dans quels cas est-il utilisé ?

L’Observer design pattern est tout par­ti­cu­liè­re­ment utile dans les ap­pli­ca­tions basées sur des com­po­sants dont le statut est

  • d’une part, fortement observé par les autres com­po­sants et
  • d’autre part, soumis à des mo­di­fi­ca­tions ré­gu­lières.

Parmi les cas d’uti­li­sa­tion typiques, on trouve les IGU (Graphical User In­ter­faces), des in­ter­faces servant à la com­mu­ni­ca­tion avec un logiciel et per­met­tant une uti­li­sa­tion facile par les uti­li­sa­teurs. Dès que des données sont modifiées, elles doivent être ac­tua­li­sées dans tous les com­po­sants de l’IGU, une tâche qui peut être assurée de façon optimale grâce à la structure sujet/ob­ser­va­teur de l’Observer pattern. Les pro­grammes utilisant des ensembles de données à vi­sua­li­ser (tableaux clas­siques ou dia­grammes gra­phiques) profitent également de l’or­ga­ni­sa­tion effectuée par ce modèle de con­cep­tion.

En principe, l’Observer design pattern ne comporte aucune res­tric­tion en ce qui concerne le langage de pro­gram­ma­tion utilisé. Pour que l’im­plé­men­ta­tion de ce modèle soit per­ti­nente, il suffit que le paradigme orienté objet soit supporté. Parmi les langages dans lesquels l’uti­li­sa­tion de ce patron est très appréciée, on trouve notamment C#, C++, Java, Ja­vaS­cript, Python et PHP.

Observer pattern : exemple d’uti­li­sa­tion du patron de con­cep­tion Ob­ser­va­teur

L’im­plé­men­ta­tion exacte de l’Observer design pattern dans les dif­fé­rents langages de pro­gram­ma­tion peut fortement varier. L’idée de base reste toutefois la même : rendre plus ac­ces­sible un objet donné ou son statut à une multitude d’autres objets.

Dans notre exemple, un texte publié par le « narrateur » doit être affiché dans les champs de texte de plusieurs « auditeurs ». À cet effet, la classe narrateur (le sujet) étend la classe Ob­ser­vable avec la méthode ad­dOb­ser­ver(). Ceci permet d’ajouter des auditeurs (les ob­ser­va­teurs). Par ailleurs, la méthode set­Chan­ged() est in­tro­duite. Cette méthode en­re­gistre les mo­di­fi­ca­tions apportées au sujet et appelle no­ti­fyOb­ser­vers() en cas de mo­di­fi­ca­tions afin d’en informer tous les ob­ser­va­teurs.

class narrateur extends Observable {
	public narrateur(){
		this.addObserver(new auditeur_1());
		this.addObserver(new auditeur_2());
		tell("texte");
	}
	public void tell(String info){
		if(countObservers()>0){
			setChanged();
			notifyObservers(info);
		}
	}
}

Par ailleurs, les ob­ser­va­teurs ont besoin d’une im­plé­men­ta­tion de l’interface ob­ser­va­teur incluant la méthode udpate() et deux arguments : l’objet observé et la mo­di­fi­ca­tion sous la forme d’une instance d’objet (Con­cre­te­Sub­ject).

class auditeur extends JFrame implements Observer{
	private JTextField field;
	public auditeur(){
		field1 = new JTextField("a");
		add(field);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(300, 50);
		setVisible(true);
	}
	public void update(Observable o, Object arg) {
		field.setText((String) arg);
	}
}
Aller au menu principal