Design pattern : Visiteur

April 9, 2015

VisitorDiagram.svg

Cette semaine je vais vous présenter un nouveau design pattern que je trouve assez intéressant : le  design pattern visiteur.

Le pattern Visiteur (Visitor) permet de séparer de manière claire un algorithme d’une structure de donnée. L’algorithme n’est donc pas implémenté dans la classe mais dans des classes externes.

On limite ainsi tout couplage entre les données et leurs traitement ce qui permet d’ajouter des traitements a nos structures de données sans avoir a les modifier.  De plus la classe externe est informé du type exact de l’objet qu’il visite a l’aide du principe du double dispatch ( bon sauf en php ou la signature des méthodes ne prends pas en compte le type des entrées).

 

 Implémentation du design pattern visiteur

 

Bien que souvent évoqué comme complexe ce design pattern est relativement simple. Notre classe visitable (c’est a dire notre structure de donnée) possède une méthode accept qui nous permet d’injecter notre visiteur (on précise une interface correspondant aux visiteurs voulu en type d’entrée).

En même temps les visiteurs concret implémente une interface qui contient une méthode visit par type d’objet visitable (ainsi on se sert du typages dynamique pour lors de l’utilisation appellera la bonne méthode – double dispatch).

Dans notre objet visitable on appellera donc la methode visit de notre visiteur en lui passant l’objet lui même.

 

Cas d’utilisation en PHP

Pour cet article j’ai en premier lieu fait une solution en PHP avant de me rendre compte que le typage faible et de ce fait la façon dont est calculer la signature des méthodes nous empêche de redéfinir une méthode avec des types différents. De ce fait dans cet exemple nous n’avons pas les avantages du double dispatch toutefois cela permet d’avoir un exemple plus simple pour commencer a voir ce pattern.

 

Grace au design pattern visiteur nous allons mettre en place un système de rendu d’un document. Notre document sera un simple objet contenant un tableau clef-valeur. Le but est d’afficher le contenu de l’objet de plusieurs façon différente : plain text, html et xml.  Pour faire cela une solution triviale serait de faire une classe renderer et dedans créer une méthode par type de rendu. Lors d’un ajout/suppression de méthode de rendu on éditerai ce fichier. Les deux principaux inconvénient de cette méthode a mon gout sont que :

Nous allons donc utiliser le design pattern visiteur. Chaque type de renderer sera une classe concrété ayant le rôle de visiteur et notre document (ici ConfigDocument) aura le rôle de classe visitable.

Ainsi pour gérer les différents types de rendu on aura juste a injecter le bon renderer via accept puis récupérer la sortie au niveau de notre renderer. Le fait d’avoir du html, xml ou autre ne dépends que du renderer que nous avons injecter.   Si cela vous semble déjà merveilleux, je vous conseille de lire attentivement la suite.  

Cas d’utilisation en JAVA

En java la principale modification est que chaque visiteur contient plusieurs méthodes accept : une part type d’objet quelle peut visiter. De cette façon on peut exécuter du code différent selon le type d’objet qui est visité et ceci au runtime. Voici un exemple simple pour illustrer ceci :            

 

Conclusion

 

C’est tout pour ce design pattern, en espérant le voir plus souvent utilisé même si on y pense pas tout le temps.  J’espère que vous comprenez un peu mieux l’intérêt du visiteur et surtout comment le mettre en oeuvre. Si ce n’est pas le cas, je répondrai aux questions dans les commentaires.

comments powered by Disqus