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.