Le design pattern fabrique

Centraliser la construction des objets à un seul endroit.

Le but de ce tutoriel est d'expliquer le fonctionnement du design pattern fabrique.

Factory Method (nom anglais) est l'un des designs pattern les plus simples à appréhender. Il n'en est pas moins indispensable dans bien des situations.

Un cas concret

Dans mon entreprise je développe et maintiens une application web qui peut se connecter à différentes bases de données. Le problème c'est qu'il y a une base de données MySQL, une base Oracle et bientôt une base PostGreSQL.

Cette application n'utilisant pas d'ORM, j'ai 3 classes (MySQL, Oracle et PostGreSQL) qui me permettent de me connecter aux différentes bases.

Problèmes de la situation :

  • Dans mon code il y a des "new MySQL()", "new Oracle()", "new PostGreSQL()" => si un jour l'une des bases change, je devrai repasser sur tous les fichiers.
  • Rien n'oblige les 3 classes à avoir le même squelette. Par exemple la classe MySQL peut avoir une méthode executerRequete() et la classe Oracle une méthode execReq(). Donc le jour ou la base Oracle devient une base MySQL je devrai modifier, un peu partout dans le code, des noms de méthodes et peut être même la façon de les utiliser.

Le design pattern Factory Method

Pour le premier point, ce qu'il nous faut c'est une méthode qui prend un paramètre en entrée. Selon ce paramètre, la méthode retournera une instance de l'un ou l'autre des SGBD cités ci-dessus.

Pour le deuxième point, rien de plus simple. Il suffit que les classes de SGBD implémentent une interface. Avec ce contrat, les développeurs seront obligés de donner le même squelette à un certain nombre de méthodes.

Nous allons créer une classe "FabriqueBase" qui servira de fabrique.

FabriqueBase.php

class FabriqueBase { public static function get($baseNom) { switch ($baseNom) { case 'zaphod': return (new MySQL()); break; case 'arthur_dent': return (new PostGreSQL()); break; case 'marvin': return (new Oracle()); break; } } } $base = FabriqueBase::get('zaphod'); $base->executer($requete); ...

Comme vous le voyez, je ne dois maintenant changer le code qu'à un seul endroit.