Observer

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
L'observation est une activité adaptée à des personnes patientes. En développement la dépendance est la même et uniquement certains objets peuvent s'endormir en attendant un événement précis. Surtout dans un design pattern qui s'appelle justement observateur.

Observer (l'observateur) est le patron de conception où un objet possède une liste des écoteurs qui, à l'arrivée d'un événement précis, sont notifiés. Cette introduction à l'observateur ressemble un peu au fonctionnement de Twitter. Là aussi un émetteur (compte) possède plusieurs écouteurs (followers). Ces derniers sont informées à chaque fois qu'une nouvelle information est publiée par l'émetteur.

Comme on peut en déduire du descriptif, 4 acteurs participent dans ce design pattern :
- observable : définit l'interface qui est observée. Elle est connue aussi sous le nom du sujet.
- concrete observable : définit l'implémentation concrète de l'objet observé. Son but consiste à maintenir la liste des écouteurs et des les notifier à chaque fois où un événement se produit.
- observer : définit l'interface qui observe (écoute) un sujet.
- concrete observer : définit l'implémentation concrète de l'interface qui observe le sujet. Elle est appelée aussi l'observateur.

L'observateur est très utile dans toutes les situations où la modification d'un objet doit être réflétée dans un autre objet et quand ces 2 objets ne doivent pas être liés d'une manière serré. Autrement dit, dans toutes les situations où ces objets doivent fonctionner indépendamment. Un autre bon exemple d'utilisation de l'observateur est toute la programmation orientée événement. Cela trouve son utilité dans toutes les applications sur les smartphones où un événement, par exemple la réception d'un appel, doit être enregistré par plusieurs applications.

Exemple d'observer
Nous, dans notre exemple, on utilisera la situation du monde footballistique. De l'un côté on aura un joueur très prometteur et talentueux. De l'autre, on aura deux scouts qui sont à la recherche de nouveaux talents. Cependant, ces deux scouts auront des méthodes d'appréciation de joueur très différentes. Un va proposer un contrat au footballeur uniquement quand ce dernier apprendra à dribbler. Le second proposera le contrat à chaque fois quand le joueur complétera 3 nouvelles compétences.


interface Player {
public void addSkill(String skillName);
}

class TalentedPlayer implements Player {
private List scouts = new ArrayList();
private List skills = new ArrayList();

public TalentedPlayer() {
this.scouts.add(new FrenchScout());
this.scouts.add(new GermanScout());
}

@Override
public void addSkill(String skillName) {
this.skills.add(skillName);
for (Observer scout : this.scouts) {
scout.notify(skillName);
}
}
}

On voit ici la partie observable avec l'interface et son implémentation concrète. On remarque que l'implémentation concrète possède une liste des scouts (observateurs). A chaque fois que le joueur apprendra une nouvelle compétence, ces scouts en seront notifiés dans la méthode addSkill(String skillName).


interface Observer {
public void notify(String info);
}

class FrenchScout implements Observer {
@Override
public void notify(String info) {
if (info.equals("dribble")) {
System.out.println("Hi TalentedPlayer ! We propose to you an 3-years contract for you dribble skills. You want to play for us ?");
}
}
}


class GermanScout implements Observer {
private int notifiedSkills = 0;

@Override
public void notify(String info) {
notifiedSkills++;
if (notifiedSkills == 3) {
System.out.println("Hi TalentedPlayer ! You have already 3 skills. Would you play to our team for next 3 years ?");
}
}
}

Ici la partie observateur. On voit que les deux observateurs ont des méthodes d'appréciation différentes. L'ensemble collé dans le code client donnera ceci :

TalentedPlayer player = new TalentedPlayer();
player.addSkill("dribble");
player.addSkill("sprint");
player.addSkill("head shoot");


Avec ce résultat :

Hi TalentedPlayer ! We propose to you an 3-years contract for you dribble skills. You want to play for us ?
Hi TalentedPlayer ! You have already 3 skills. Would you play to our team for next 3 years ?


On remarque sur notre exemple que la liaison entre le joueur et les scouts est transparente. Sans regarder le code source, on ne saura jamais que les deux sont liés. Mais malgré cette absence de liaison forte, les scouts savent très bien de ce qu'est capable le joueur prometteur. Et ils ne manqueront pas de lui proposer le contrat si ses compétences seront jugées satisfaisantes. Et c'est cette notification qui se trouve au cœur du patron de conception l'observateur.
Bartosz KONIECZNY 27-11-2013 06:20 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 PHP

Utiliser XPath pour calculer le nombre d'apparitions d'un élément.

XPath est un langage qui sert à se déplacer au sein d'un document XML. Il contient beaucoup de fonctionnaltiés utilies lors de l'analyse de ces documents. Par exemple, pour voir le nombre d'apparition d'un tag, il suffit d'utiliser la méthode count et placer comme son paramètre le chemin vers les éléments à calculer. Imaginons qu'on veut calculer le nombre de noeds d'erreur. En PHP cela va se présenter ainsi :

// $this->xpath is the instance of DOMXPath
echo (int)$this->xpath->evaluate("count(/error)");