Designs Patterns : Modéle Observateur
Le modéle Observateur est un mécanisme de diffusion d'évenements, il diffuse des mises à jour d'un sujet, à des écouteurs qui se sont enregistré à celui-ci.
On l'utilise pour s'occuper de la gestion de thémes visuels, dans des jeux, il permet de diffuser simplement et aisément les modifications apportées à un objet. Les écouteurs se chargeant par la suite de faire ce qu'ils veulent des informations reçues par notification.
La seule contrainte étant que les écouteurs doivent définir une méthode pour recevoir les mises à jour.
Lorsque le sujet change d'état, il appelle notifiyObs
, qui lance update
sur tous les observateurs de ce sujet, update
peut effectuer des taches trés différentes selon les observateurs …
Présentation
Voici les class nécessaires à l'élaboration de ce Design Pattern :
- Observateur
- Défini les méthodes qui vont être étendues aux sujetx.
- Stocke les observateurs du sujet.
- Permet l'ajout, la suppression et la notification des observateurs d'un sujet.
- IObservateur
- Interface que les observateurs de sujets doivent implementer ( être notifié, se désabonner ).
- Sujet
- le sujet étends
Observateur
, et doit contenir dans ses méthodes des appels à la notification de ses observateurs.
- ObservateurSujet
- Doit implémenter
IObservateur
.
Implémentation
Class Observateur :
import IObservateur; class Observateur { // boolean définissant si le sujet a changé ou non. private var _bChanged : Boolean = false; // stockage des observateurs private var _aObservateurs : Array; // constructeur public function Observateur () { _aObservateurs = []; } // ajouter un observateur public function addObs (o : IObservateur) : Boolean { if (o == null) { return false; } var l : Number = _aObservateurs.length; // on n'autorise qu'une seule occurence d'un observateur précis. // pour éviter les doubles notification. for (var i : Number = 0; i < l; i ++) { if (_aObservateurs [i] == o) { return false; } } _aObservateurs.push (o); return true; } // supprimer un observateur public function removeObs (o : IObservateur) : Boolean { var l : Number = _aObservateurs.length; for (var i : Number = 0; i < l; i ++) { if (_aObservateurs [i] == o) { _aObservateurs.splice (i, 1); return true; } } return false; } // notifier les observateurs public function notifyObs (oInfo : Object) : Void { if (oInfo == undefined) { oInfo = null; } // on évite un appel inutile si le sujet n'a pas changé if ( ! _bChanged) { return; } // on effectue une copie du tableau d'observateurs, pour ne notifier que ceux actuellement inscrit. var _aObservateursCopy : Array = _aObservateurs.slice (0); clearChanged (); var l : Number = _aObservateursCopy.length for (var i : Number = l - 1; i >= 0; i --) { // on lance la fonction que doivent implementer les observateurs _aObservateursCopy [i].update (this, oInfo); } } // supprimer tout les observateurs public function clearObs () : Void { _aObservateurs = []; } private function setChanged () : Void { _bChanged = true; } private function clearChanged () : Void { _bChanged = false; } public function hasChanged () : Boolean { return _bChanged; } public function countObs () : Number { return _aObservateurs.length; } }
Interface IObservateur :
import Observateur; interface IObservateur { public function update (o : Observateur, infoObj : Object) : Void; public function destroy () : Void; }
Class Sujet :
import Observateur; class Sujet extends Observateur { private var _sMsg : String; public function Sujet () { _sMsg = ""; } public function setMsg (s : String) { _sMsg = s; // on indique que l'état du sujet a changé. setChanged (); var o : Object = { msg : _sMsg } // on notifie les observateurs du sujet. notifyObs (o); } }
Class ObservateurSujet :
import IObservateur; import Sujet; class ObservateurSujet implements IObservateur { private var _oSujet : Sujet; // on l'occurence du sujet lors de la creation de son observateur. public function ObservateurSujet (o : Sujet) { _oSujet = o; } // fonctions obligatoires, à implementer pour tout les observateurs. public function update (o : Observateur, oInfo : Object) : Void { trace ("MAJ : "+oInfo.msg); } public function destroy () : Void { _oSujet.removeObs (this); } }
Usage
import Observateur; import Sujet; import ObservateurSujet; // création du sujet var oS:Sujet = new Sujet(); // création de son observateur ( sujet en argument ) var oT:Traceur = new ObservateurSujet(oS); // on ajoute l'observateur au sujet. ( référence croisée ) oS.addObs(oT); // on lance une notification oS.setMsg("Je notifie à mes observateurs que j'ai changé"); /* Résultat : MAJ : Je notifie à mes observateurs que j'ai changé */
Notes
Vous pouvez adapter cela à vos besoins, par exemple, ne pas envoyer les informations de modification, mais juste indiquer que l'etat du sujet à changer, laissant ainsi à votre observateur le soin de lancer une méthode qui lui convient sur le sujet qu'il surveille.
