[DUMD 12/24] Le design pattern template method

Auteur du billet de blog : Nicolas Hilaire - Neotech Solutions

Nicolas Hilaire

Consultant .NET
  Publié le vendredi 2 décembre 2016

Artisan logiciel particulièrement intéressé par les technologies .NET. Polyvalent et curieux, je suis néanmoins à l'écoute des autres technologies du marché. MVP (Microsoft Most Valuable Professional) de 2007 à 2014, je suis également auteur d'un ouvrage pour apprendre le C#, à destination des débutants et de plusieurs MOOCs sur le C#, Windows Phone ou ASP.NET MVC...

Douzième billet sur comment devenir un meilleur développeur. Pour retrouver le sommaire ainsi que tous les liens, rendez-vous sur le premier billet.

Parlons maintenant du design pattern template method. Je voulais absolument parler de ce design pattern car il utilise l'héritage. Et je vous avais promis dans les premiers billets que nous verrions des endroits où l'héritage est utilisé à bon escient.

C'est le cas de ce patron de conception que l'on appelle en français : patron de méthode.

 

Le patron de méthode en action

Retournons dans notre café où nous avons besoin d'écrire un algorithme pour faire un café et un thé. Voici un premier essai :

 

 

Ok, je le vois aussi clignoter. DRY. DRY. DRY. !!!

 

Il y a indubitablement des choses qui se répètent, on voit bien que la préparation du thé et du café est "presque" identique. Mais voilà, c'est ce "presque" qui nous embête. On a un algorithme qui est globalement celui-ci :

  • Faire bouillir de l'eau
  • Préparer la boisson (faire infuser ou faire passer le café dans le filtre)
  • Ajouter du sucre
  • Ajouter des suppléments (du citron pour le thé, rien pour le café)
  • Remuer

C'est là que le patron de méthode fait son arrivée. Il permet de définir les étapes d'un algorithme et permet aux sous-classes de fournir l'implémentation d'une ou plusieurs de ces étapes.

On a donc besoin d'une classe abstraite qui définit les étapes de la préparation d'une boisson :

 

 

Les étapes qui diffèrent sont abstraites et sont à substituer dans les classes filles, The et Cafe :

 

 

Et la préparation des boissons se fait en un clin d’œil :

 

 

Oui, je sais, dans le billet sur les rappels POO, j'ai dit que mutualiser des comportements dans une classe de base c'était mal. :(


C'est vrai, j'ai dit ça. Disons que j'ai surtout dit que ce n'était sans doute pas la meilleure option et qu'il fallait réfléchir afin de voir si c'était la solution la plus adaptée.

Eh bien c'est justement un cas où on se retrouve ici avec une solution qui va bien. Le design pattern template method nous incite à avoir des comportements qui doivent absolument être suivis par les classes filles. On retrouve cette notion "d'algorithme" général.

Mais le point vraiment particulier c'est que c'est la classe de base qui appelle des comportements qui sont définis dans les classes filles, alors que dans l'exemple que nous avions vu, c'était l'inverse.

 

Petite variante

Il y a un élément qui peut paraître un peu dommage, dans le cas de la préparation du café. Vous avez vu que nous avons implémenté la méthode d'ajout de suppléments et qu'elle est vide.

A partir du moment où certaines parties de l'algorithme peuvent être optionnelles, on peut les implémenter sous la forme de méthodes possédant une implémentation par défaut mais se déclarant candidates à la substitution. En C# on utilise le mot clé virtual :

 

 

On voit ici que la méthode ADesSupplements fourni une implémentation par défaut, de même pour la méthode AjouterLesSupplements(). Ainsi, la classe Cafe n'aura pas besoin d'en fournir une implémentation :

 

 

On appelle ces méthodes des méthodes adaptateur.

L'inconvénient de cette pratique est qu'elle impose de connaître un minimum la structure de la classe de base afin de savoir quelles méthodes possédant un comportement par défaut nous souhaitons substituer. D'ailleurs, savons-nous toujours quel est le comportement par défaut ? A contrario, les méthodes abstraites nous forcent à implémenter ces méthodes, sans cela nos classes ne compilent pas.

 

Conclusion

Voilà une utilisation de l'héritage qui est bonne à prendre, mais à utiliser en connaissance de cause et toujours avec jugeote et parcimonie. A part ça, le patron de méthode est une solution intéressante dès que vous avez un algorithme général que des classes dérivées doivent absolument suivre ; tout en offrant la possibilité de redéfinir certaines parties de l'algorithme pour le spécialiser.

 

Prochain billet sur le design pattern Repository.

Commentaires