Le Pattern : Abstract Factory

Le pattern Abstract Factory est un design pattern de création qui permet de créer des objets cohérents et compatibles, sans exposer les détails de l'implémentation au code client.

En utilisant l'Abstract Factory, il est facile d'ajouter de nouvelles familles d'objets simplement en implémentant une nouvelle classe concrète de la fabrique. Ce pattern est très utile pour la conception de systèmes modulaires et extensibles.

  • - Probleme

    Supposons que nous développons une application d'animalerie en PHP. Notre application doit être capable de créer différents types d'animaux, tels que des lions, des tigres, des éléphants, des singes et des crocodiles. Chaque type d'animal doit être créé de manière cohérente et compatible avec les autres types d'animaux.

    Cependant, la création de chaque type d'animal peut être complexe, avec de nombreux détails d'implémentation différents en fonction de l'espèce. Par exemple, la création d'un lion peut nécessiter la création d'une crinière et la gestion de sa couleur, tandis que la création d'un crocodile peut nécessiter la création d'une peau écailleuse et la gestion de sa texture.

  • Le pattern Abstract Factory peut être utilisé pour résoudre ce problème en fournissant une interface commune pour la création d'animaux, tout en permettant une implémentation spécifique pour chaque type d'animal. Nous pouvons créer une interface AnimalFactory qui définit des méthodes pour créer chaque type d'animal, telles que createLion(), createTiger(), etc.

    Nous pouvons ensuite créer des implémentations concrètes de AnimalFactory, telles que AfricanAnimalFactory et AsianAnimalFactory, qui créent des animaux cohérents et compatibles pour chaque région géographique.

    Le code client peut alors utiliser une instance de l'implémentation appropriée de AnimalFactory pour créer les différents types d'animaux. Cela permet de créer des objets cohérents et compatibles, sans que le code client ait besoin de connaître les détails de l'implémentation. En outre, il est facile d'ajouter de nouveaux types d'animaux simplement en implémentant une nouvelle classe de fabrique concrète.

  • La méthodologie d'implémentation du pattern Abstract Factory en PHP consiste à :

    - Créer une interface ou une classe abstraite AbstractFactory qui définit les méthodes de création d'objets. Les différentes implémentations de cette interface ou classe abstraite seront les différentes familles d'objets que la fabrique abstraite peut créer.

    - Ensuite, nous créons des classes concrètes qui implémentent AbstractFactory. Ces classes sont responsables de la création des objets concrets. Chaque classe concrète de la fabrique crée des objets cohérents et compatibles.

    - Enfin, nous utilisons la fabrique concrète pour créer des objets. Nous créons une instance de la fabrique concrète appropriée, en fonction de la famille d'objets que nous voulons créer. Nous utilisons ensuite les méthodes de création d'objets pour créer les objets dont nous avons besoin.

    L'avantage de cette approche est qu'elle permet de créer des objets cohérents et compatibles, sans que le code client ait besoin de connaître les détails de l'implémentation. Cela permet également de rendre le code plus facilement extensible et maintenable, car il est facile d'ajouter de nouvelles familles d'objets simplement en implémentant une nouvelle classe concrète de la fabrique.

  • Supposons que nous ayons une animalerie et que nous voulions créer une classe de fabrique qui nous permet de créer des objets Cat et Dog.

    Voici comment cela peut être implémenté en utilisant l'Abstract Factory :

    Tout d'abord, nous allons créer une classe abstraite AnimalFactory qui contiendra deux méthodes abstraites : createCat() et createDog(). Ces méthodes abstraites seront implémentées dans des classes concrètes SmallAnimalFactory et BigAnimalFactory, qui sont des sous-classes de la classe abstraite AnimalFactory.


    abstract class AnimalFactory {
    abstract public function createCat();
    abstract public function createDog();
    }

    class SmallAnimalFactory extends AnimalFactory {
    public function createCat() {
    return new SmallCat();
    }
    public function createDog() {
    return new SmallDog();
    }
    }

    class BigAnimalFactory extends AnimalFactory {
    public function createCat() {
    return new BigCat();
    }
    public function createDog() {
    return new BigDog();
    }
    }


    Ensuite, nous allons créer deux classes abstraites Cat et Dog qui contiennent des méthodes communes pour tous les animaux, telles que speak() et getSize(). Ces classes seront ensuite étendues par des classes concrètes telles que SmallCat, SmallDog, BigCat et BigDog.


    abstract class Cat {
    abstract public function speak();
    abstract public function getSize();
    }

    abstract class Dog {
    abstract public function speak();
    abstract public function getSize();
    }

    class SmallCat extends Cat {
    public function speak() {
    return "Miaou";
    }
    public function getSize(): string {
    return "Small cat";
    }
    }

    class SmallDog extends Dog {
    public function speak() {
    return "Waaf";
    }
    public function getSize() {
    return "Small dog";
    }
    }

    class BigCat extends Cat {
    public function speak() {
    return "Schhh";
    }
    public function getSize() {
    return "Big cat";
    }
    }

    class BigDog extends Dog {
    public function speak() {
    return "Grrr";
    }
    public function getSize() {
    return "Big dog";
    }
    }


    Enfin, nous pouvons utiliser ces classes pour créer des objets de manière cohérente et facile à maintenir, en utilisant la classe AnimalFactory.


    $smallFactory = new SmallAnimalFactory();
    $smallCat = $smallFactory->createCat();
    $smallDog = $smallFactory->createDog();
    echo $smallCat->speak(); // Affichera "Miaou"
    echo $smallCat->getSize(); // Affichera "Small cat"
    echo $smallDog->speak(); // Affichera "Waaf"
    echo $smallDog->getSize(); // Affichera "Small dog"

    $bigFactory = new BigAnimalFactory();
    $bigCat = $bigFactory->createCat();
    $bigDog = $bigFactory->createDog();
    echo $bigCat->speak(); // Affichera "Shhh"
    echo $bigCat->getSize(); // Affichera "Big cat"
    echo $bigDog->speak(); // Affichera "Grrr"
    echo $bigDog->getSize(); // Affichera "Big dog"

    La classe AnimalFactory contient des méthodes abstraites qui définissent les méthodes de création d'objets. Les classes concrètes SmallAnimalFactory et BigAnimalFactory étendent AnimalFactory et fournissent des implémentations concrètes pour ces méthodes de création d'objets.

    Chaque classe concrète de la fabrique crée des objets de types différents mais cohérents. Par exemple, la SmallAnimalFactory crée des objets SmallCat et BigDog tandis que la BigAnimalFactory crée des objets BigCat et BigDog.

    Cela permet d'abstraire la création d'objets et de la rendre facilement interchangeable. Par exemple, si nous décidions d'ajouter un troisième type d'animal, tel qu'un Bird, nous n'aurions qu'à ajouter une nouvelle méthode abstraite à la classe AnimalFactory et implémenter cette méthode dans les classes concrètes de la fabrique sans avoir à modifier le code existant.

    En utilisant l'Abstract Factory, nous pouvons créer des objets cohérents de manière simple et maintenable, en encapsulant la logique de création d'objets.