Vous êtes sur la page 1sur 10

Abstract Factory

Intention
Le patron Abstract Factory fournit une interface pour créer des familles d'objets liés
ou dépendants sans spécifier leurs classes concrètes.
Objectif :

Le patron Abstract Factory permet la création de familles d’objets ayant un lien ou


interdépendants.

Exemple classique :

Lorsqu’une classe gère plusieurs types de produits, déplacer les méthodes fabrique
dans des fabriques individuelles ou dans une implémentation à part entière d’une
fabrique abstraite est souvent plus pratique.

Problème
On souhaite pouvoir créer dynamiquement des familles d'objets apparentés (par
exemple des instances d'une même classe), tout en permettant de reporter certaines
décisions jusqu'à la phase d'exécution (par exemple le choix d'une classe concrète
pour réaliser une interface donnée).
Solution
Créer des familles de produits liés fonctionnellement avec plusieurs fabriques, donc
on obtient plusieurs types d'objets retournés par chaque fabrique (plusieurs
méthodes d'instanciation par Factory method).
Principe de base du patron Abstract Factory

Pour ce faire, il faut définir des interfaces pour chaque produit de la famille de
produits. Toutes les autres variantes de produits peuvent ensuite se servir de ces
interfaces. Ensuite, définir la fabrique abstraite, une interface contenant une liste de
méthodes de création pour toutes les familles de produits. Ces méthodes doivent
renvoyer tous les types de produits abstraits des interfaces déjà créées.

Pour chaque variante d’une famille de produits, définir une classe fabrique qui
retourne un certain type de produits et qui implémente l’interface FabriqueAbstraite.
Enfin, le client travaille simultanément avec les interfaces abstraites des fabriques et
des produits.
Structure
Diagramme UML du patron Abstract Factory
1. Le client envoie une requête à AbstractFactory pour ConcreteFactory1.
2. L'AbstractFactory crée une instance de ConcreteFactory1 et la renvoie.
3. Le client envoie une requête à ConcreteFactory1 pour la création de ProductA.
4. ConcreteFactory1 crée une instance de ProductA1 qui est membre de Family1 et
la renvoie.
5. Maintenant, le client envoie une requête à AbstractFactory pour
ConcreteFactory2.
6. L'AbstractFactory crée une instance de ConcreteFactory2.
7. Le client envoie une requête à ConcreteFactory2 pour la création de ProductA.
8. La ConcreteFactory2 crée une instance de ProductA2 qui est membre de
Family2 et la renvoie.

Participants
● AbstractFactory déclare l'interface pour les opérations qui créent des objets
abstraits,
● ConcreteFactory implémente les opérations qui créent les objets concrets,
● AbstractProduct déclare une interface pour un type d'objet,
● ConcreteProduct définit un objet qui doit être créé par la fabrique concrète
correspondante et implémente l'interface AbstractProduct.

Le Client utilise seulement les interfaces déclarées par AbstractFactory et par les
classes AbstractProduct
Collaborations & implémentation

Une seule instance de fabrique concrète est créée à l'exécution. Cette fabrique crée
les objets avec une implémentation spécifique.
Pour créer différentes sortes d'objets, les clients doivent utiliser différentes fabriques
concrètes. La fabrique abstraite défère la création des objets à ses sous-classes
concrètes
Implémentation

Les fabriques sont souvent des singletons. Ce sont les sous-classes concrètes qui
font la création, en utilisant le plus souvent une Factory Method.

Si plusieurs familles sont possibles, la fabrique concrète utilise Prototype (créer de


nouveaux objets en copiant un prototype existant).
Le code client appelle les méthodes de création d’un objectFactory plutôt que de
créer directement les produits à l’aide d’un constructeur (opérateur new).

Chaque fabrique possède sa propre variante de produit, tous ses produits seront
compatibles. Il suffit donc de créejurste une nouvelle classe concrète Fabrique et
passez-la au code client.

En effet, ce dernier manipule les fabriques et les produits uniquement via leurs
interfaces abstraites, ce qui lui permet de travailler avec n’importe quelle variante de
produit créée par un objectFactory.

Conséquences :
● Isolation des classes concrètes,
● Echange facile des familles de produit,
● Encouragement de la cohérence entre les produits,
● Prise en compte difficile de nouvelles formes de produit.
Exemple illustratif
En continuant avec l’exemple de fabrication de télephones, nous constatons quelque
soit la façon dont l'usine divise l'abstraction, les deux modèles (Simple Factory et
Factory Method) ne concernent qu'un seul type de produit Téléphone (produit
abstrait). Si vous souhaitez générer un autre produit Laptop, vous ne pouvez pas, il
faut utiliser Abstract Factory pour créer une Usine de Laptop.

Avec Factory Method, nous devons copier et modifier complètement tout le code de
gestion de la production du téléphone et le faire avec Laptop. Évidemment, ce n’est
pas une bonne manière propice à l'expansion et à la maintenance.

Nous commençons par la définition de l'interface des produits Laptop (AbstractLaptop)


:
public interface Laptop {
void make();
}
Puis définir la classe SamsungLaptop qui implémente l’interface Laptop :
public class SamsungLaptop implements Laptop {
public SamsungLaptop() {
this.make();
}
@Override
public void make() {
System.out.println("make Samsung Laptop!");
}
}

Ensuite, nous définissons les produits MacLaptop en implémentant l’interface Laptop :


public class MacLaptop implements Laptop {
public MacLaptop() {
this.make();
}
@Override
public void make() {
System.out.println("make MAC Laptop!");
}
}

Vous devez modifier la définition des classes liées à la fabrique en ajoutant une
interface de fabrication de produits Laptop à la Classe AbstractFactory :
public interface AbstractFactory {
Phone makePhone();
Laptop makeLaptop();
}

Par la suite, on définit la classe SamsungFactory pour la fabrication des Laptop


Samsung (ConcreteFactory1) en implémentant l’interface AbstractFactory :
public class SamsungFactory implements AbstractFactory{
@Override
public Phone makePhone() {
return new Galaxy();
}
@Override
public Laptop makeLaptop() {
return new SamsungLaptop();
}
}
De la même façon, on définit la classe AppleFactory qui ajoute la fabrication des
Laptop Apple ( ConcreteFactory2) en implémentant l’interface AbstractFactory :
public class AppleFactory implements AbstractFactory {
@Override
public Phone makePhone() {
return new IPhone();
}
@Override
public Laptop makeLaptop() {
return new MacLaptop();
}
}

La Classe Client illustre un cas d’utilisation de création des Télephones et Laptop


des usines Apple et Samsung :
public class Client {
public static void main(String[] arg) {
AbstractFactory samsungFactory = new
SamsungFactory();
AbstractFactory appleFactory = new AppleFactory();
samsungFactory.makePhone(); // make
Samsung phone!
samsungFactory.makeLaptop(); // make
Samsung Laptop!
appleFactory.makePhone(); // make
iphone!
appleFactory.makeLaptop(); // make MAC!
}
}
Diagramme UML du code ci-dessus
Usages connus
● Les applications graphiques, etc.
● Les frameworks ou les bibliothèques de classes
● Exemples de modèles de conception d'usine dans JDK, il l'en existe plusieurs
exemples du modèle Factory :
○ La méthode valueOf() est utilisée dans les classes String et wrapper. Elle
renvoie un objet créé par la fabrique équivalent à la valeur du
paramètre passé.
○ la méthode newInstance() qui est utilisée pour créer et renvoyer une
nouvelle instance à partir de la méthode d'usine à chaque appel :
javax.xml.parsers.DocumentBuilderFactory#newInstance(),
javax.xml.transform.TransformerFactory#newInstance() et
javax.xml.xpath.XPathFactory#newInstance().

Avantages et inconvénients
Avantages
● Encapsuler la création d'objets, vous pouvez contrôler les classes d'objets
créées par une application. De plus, le client ne connaît pas l'implémentation
concrète et ne peut passer que par l'interface ou la classe abstraite.
● Favoriser la cohérence entre les familles d'objets car il garantit que si une
famille d'objets est conçue pour fonctionner ensemble, l'application utilise les
objets d'une famille à la fois. Avec ce patron, c'est très facile à réaliser.
● Éviter le couplage étroit entre les produits concrets et le code client.
Inconvénients
● Ajouter une nouvelle famille d'objets ne sera pas aisé car la super-usine de
l'Abstract Factory (interface ou classe abstraite) fixe les familles d'objets qui
peuvent être créées. Cela nous obligera à changer la fabrique abstraite et
toutes les sous-classes.

Simple Factory vs Factory Method Vs Abstract Factory

Simple Factory Factory Method Abtsract Factory

Se compose d'une Contient une classe de Contient une classe d'usine


classe de fabrique fabrique et ne peut qui peut produire une famille
chargée de créer un produire qu'un seul type de différents types d'objets.
ou plusieurs types d'objet.
d'objets.

La classe Factory est La classe Factory La classe Factory crée une


une classe simple et implémente une abstraction pour les usines en
n'implémente aucune interface/un protocole utilisant l'interface/le
interface avec une méthode protocole.
create().

La classe Factory Le sous-classement Chaque usine est spécialisée


contient une méthode décide quel est le type dans la création d'un type
qui produit un objet d'objet concret qu'il d'objet. Ainsi, on l'appelle
basé sur une entrée renvoie. aussi usine d'usines.
donnée

Une usine généralisée Une usine spécialisée Une usine généralisée


capable de produire un dans la création d'un contient une ou plusieurs
ou plusieurs types seul type d'objet. usines spécialisées produisant
d'objets. chacune un type d'objet.

Simple Factory Factory Method utilise Le modèle Abstract Factory


s'appuie sur une l'héritage et s'appuie sur utilise la composition pour
classe dérivée ou une une classe dérivée ou déléguer la responsabilité de
sous-classe pour créer une sous-classe pour la création d'un objet à une
un objet. créer un objet. autre classe
Cas d'utilisation : pour Cas d'utilisation : pour Cas d'utilisation : pour créer
créer un objet dans un créer un objet qui a plusieurs objets de la même
but précis, mais ne beaucoup de famille, préférez le modèle
vous souciez pas du dépendances et de d'usine abstraite.
type de béton configuration à effectuer, Généralement utilisé dans
approprié, préférez préférez la méthode l'injection de dépendances.
Factory. Il crée et d'usine. Parce qu'il a
renvoie l'objet une classe responsable
approprié de la création d'un type
d'objet, il peut donc bien
gérer les configurations
et les dépendances

Exemple : Exemple : PhoneFactory Exemple : PhoneFactory est


PhoneFactory crée tous est abstrait, et il y aura Factory et il y aura d’autres
les types de des usines concrètes usines concrètes pour
téléphones tels que telles que chacunes SamsungFactory et
AndroidPhone, IPhone, SamsungPhoneFactory et AppleFactory pour créer
etc. IPhoneFactory pour SamsungPhone et IPhone et
créer SamsungPhone et SamsungLaptop et MacLaptop.
IPhone

Questions
Question 1.

Qu'est-ce qu'un Factory ?


Question 2.

Qu'est-ce qu'un Factory Method ?


Question 3.

Quand utiliser chaque Patron ?


Réponses aux questions
Réponse à la question 1

Le Factory est une terminologie qui désigne une classe ou une méthode
responsable de la création/production d'un objet. Ex. : PhoneFactory est
responsable de la production des téléphones.
Réponse à la question 2

Il est responsable de la création et du retour des objets au client. Il peut accepter


une entrée indiquant le type d'objet à créer.
class PhoneFactory {
public Phone makePhone(String phoneType) {
if (phoneType.equals("Android"))
return new AndroidPhone();
else if (phoneType.equals("Apple"))
return new IPhone();
}
}

Dans cet exemple, makePhone() est la méthode de fabrique qui produit des
téléphones en fonction de l'argument phoneType qu'il reçoit.
Réponse à la question 3
● Factory ou simple Factory : quand le client a juste besoin d'une classe et ne
se soucie pas de l'implémentation concrète qu'il obtient.
● Factory Method : quand le client ne sait pas quelles classes concrètes il devra
créer au moment de l'exécution, mais souhaite simplement obtenir une classe
qui fera le travail.
● Abstact Factory : lorsque votre système doit créer plusieurs familles de
produits ou que vous souhaitez fournir une bibliothèque de produits sans
exposer les détails de mise en œuvre.

Les classes abstraites Factory sont souvent implémentées avec Factory Method.
Les méthodes d'usine sont généralement appelées dans les méthodes de modèle.

Vous aimerez peut-être aussi