0% ont trouvé ce document utile (0 vote)
23 vues1 page

Fabrique Factory Method

Le patron de conception Fabrique permet de créer des objets sans coupler le code client aux classes concrètes, facilitant ainsi l'ajout de nouveaux types d'objets. En définissant une méthode fabrique dans une classe mère, les sous-classes peuvent redéfinir cette méthode pour retourner différents types d'objets tout en respectant une interface commune. Cela rend le code plus évolutif et maintenable, tout en permettant la réutilisation d'objets existants.

Transféré par

jujudave
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
23 vues1 page

Fabrique Factory Method

Le patron de conception Fabrique permet de créer des objets sans coupler le code client aux classes concrètes, facilitant ainsi l'ajout de nouveaux types d'objets. En définissant une méthode fabrique dans une classe mère, les sous-classes peuvent redéfinir cette méthode pour retourner différents types d'objets tout en respectant une interface commune. Cela rend le code plus évolutif et maintenable, tout en permettant la réutilisation d'objets existants.

Transféré par

jujudave
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

SPRING SALE

   

 / Patrons de conception / Patrons de


création

Fabrique
Alias : Constructeur virtuel, Factory Method

 Intention
Fabrique est un patron de conception de
création qui dé;nit une interface pour créer
des objets dans une classe mère, mais
délègue le choix des types d’objets à créer
aux sous-classes.
SPRING SALE

 Problème
Imaginez que vous êtes en train de créer une
application de gestion logistique. La
première version de votre application ne
propose que le transport par camion, la
majeure partie de votre code est donc située
dans la classe Camion .

Au bout d’un certain temps, votre application


devient populaire et de nombreuses
entreprises de transport maritime vous
demandent tous les jours d’ajouter la gestion
de la logistique maritime dans l’application.

L’ajout d’une nouvelle classe au programme ne


s’avère pas si simple que cela si le reste du code est
déjà couplé aux classes existantes.

C’est super, n’est-ce pas ? Mais qu’en est-il du


code ? La majeure partie est actuellement
couplée à la classe Camion . Pour pouvoir
ajouter des Bateaux dans l’application, il
faudrait revoir la base du code. De plus, si
vous décidez plus tard d’ajouter un autre type
de transport dans l’application, il faudra
effectuer à nouveau ces changements.

Par conséquent, vous allez vous retrouver


avec du code pas très propre, rempli de
conditions qui modi;ent le comportement du
programme en fonction de la classe des
objets de transport.

 Solution
Le patron de conception fabrique vous
propose de remplacer les appels directs au
constructeur de l’objet (à l’aide de l’opérateur
new ) en appelant une méthode fabrique

spéciale. Pas d’inquiétude, les objets sont


toujours créés avec l’opérateur new , mais
l’appel se fait à l’intérieur de la méthode
fabrique. Les objets qu’elle retourne sont
souvent appelés produits.

Les sous-classes peuvent modi;er les classes des


objets retournés par la méthode fabrique.

À première vue, cette modi;cation peut


sembler inutile : nous avons juste déplacé
l’appel du constructeur dans une autre partie
du programme. Mais maintenant, vous
pouvez redé;nir la méthode fabrique dans la
sous-classe et changer la classe des produits
créés par la méthode.

Il y a tout de même une petite limitation : les


sous-classes peuvent retourner des produits
différents seulement si les produits ont une
classe de base ou une interface commune. De
plus, cette interface doit être le type retourné
par la méthode fabrique de la classe de base.

Les produits doivent tous implémenter la


même interface.

Par exemple, les classes Camion et Bateau


doivent toutes les deux implémenter
l’interface Transport , qui déclare une
méthode livrer . Chaque classe implémente
cette méthode à sa façon : les camions
livrent par la route et les bateaux livrent par
la mer. La méthode fabrique de la classe
LogistiqueRoute retourne des camions, alors

que celle de la classe LogistiqueMer


retourne des bateaux.

Tant que les classes produit implémentent une


interface commune, vous pouvez passer leurs objets
au code client sans tout faire planter.

Le code qui appelle la méthode fabrique


(souvent appelé le code client) ne fait pas la
distinction entre les différents produits
concrets retournés par les sous-classes, il les
considère tous comme des Transports
abstraits. Le client sait que tous les objets
transportés sont censés avoir une méthode
livrer , mais son fonctionnement lui

importe peu.

 Structure

1. L’interface est déclarée par le Produit et


est commune à tous les objets qui
peuvent être conçus par le créateur et ses
sous-classes.

2. Les Produits Concrets sont différentes


implémentations de l’interface produit.

3. La méthode fabrique est déclarée par la


classe Créateur et retourne les nouveaux
produits. Il est important que son type de
retour concorde avec l’interface produit.

Vous pouvez rendre la méthode fabrique


abstraite a;n d’obliger ses sous-classes à
implémenter leur propre version de la
méthode ou vous pouvez modi;er la
méthode fabrique de la classe de base
a;n qu’elle retourne un type de produit
par défaut.

Il faut bien comprendre que malgré son


nom, la création de produits n’est pas la
responsabilité principale du créateur. La
classe créateur a en général déjà un
fonctionnement propre lié à la nature de
ses produits. La fabrique aide à découpler
cette logique des produits concrets. C’est
un peu comme une grande entreprise de
développement de logiciels : elle peut
posséder un département spécialisé dans
la formation des développeurs, mais son
activité principale reste d’écrire du code,
pas de produire des développeurs.

4. Les Créateurs Concrets redé;nissent la


méthode fabrique de la classe de base
a;n de pouvoir retourner les différents
types de produits.

Notez toutefois que la méthode fabrique


n’est pas obligée de créer tout le temps de
nouvelles instances. Elle peut retourner
des objets depuis un cache, un réservoir
d’objets ou une autre source.

 Pseudo-code
Cet exemple montre comment la fabrique
peut être utilisée pour créer des éléments
d’une UI (interface utilisateur)
multiplateforme sans coupler le code client
aux classes concrètes de l’UI.

Exemple multiplateforme pour une boîte


de dialogue.

La classe de base dialogue utilise différents


éléments d’UI pour le rendu de ses fenêtres.
Ces éléments peuvent un peu varier en
fonction du système d’exploitation, mais ils
doivent garder le même comportement. Un
bouton sous Windows est aussi un bouton
sous Linux.

Lorsque la fabrique entre dans l’équation, il


est inutile de réécrire la logique de la boîte
de dialogue pour chaque système
d’exploitation. Si nous déclarons une
méthode fabrique qui crée des boutons à
l’intérieur de la classe de base dialogue, nous
pourrons par la suite sous-classer cette
dernière a;n que la méthode fabrique
retourne des boutons dotés du style
Windows. La sous-classe hérite alors du code
de la classe de base dialogue, mais grâce à la
fabrique, elle est capable d’af;cher à l’écran
des boutons à l’allure Windows.

Pour le bon fonctionnement de ce patron, la


classe de base dialogue doit utiliser des
boutons abstraits représentés par une classe
de base ou une interface dont tous les
boutons concrets hériteront. Ainsi, quel que
soit le type de boutons, le code de la classe
dialogue reste fonctionnel.

Bien sûr, cette approche fonctionne


également avec les autres éléments de l’UI.
Cependant, chaque nouvelle méthode
fabrique ajoutée à Dialogue nous rapproche
du patron de conception Fabrique abstraite.
Pas de panique, nous aborderons ce patron
plus tard !

// La classe créateur déclare la méthode fabri


// renvoyer un objet de la classe produit. Les
// créateur fournissent en général une impléme
// méthode.
class Dialog is
// Le créateur peut également fournir des
// par défaut de la méthode fabrique.
abstract method createButton():Button

// Ne vous laissez pas berner par son nom,


// principale du créateur n’est pas de fab
// produits. Il héberge en général de la l
// concerne les produits retournés par la
// Les sous-classes peuvent modifier indir
// logique métier en redéfinissant la méth
// lui faisant retourner un type de produi
method render() is
// Appelle la méthode fabrique pour cr
// Produit.
Button okButton = createButton()
// Utilise le produit.
[Link](closeDialog)
[Link]()

// Les créateurs concrets redéfinissent la mét


// changer le type du produit qui en résulte.
class WindowsDialog extends Dialog is
method createButton():Button is
return new WindowsButton()

class WebDialog extends Dialog is


method createButton():Button is
return new HTMLButton()

// L’interface du produit déclare les traiteme


// produits concrets doivent implémenter.
interface Button is
method render()
method onClick(f)

// Les produits concrets fournissent diverses


// l’interface du produit.
class WindowsButton implements Button is
method render(a, b) is
// Affiche un bouton avec le style Win
method onClick(f) is
// Attribue un événement sur un clic n
// système d’exploitation.

class HTMLButton implements Button is


method render(a, b) is
// Retourne une représentation HTML d’
method onClick(f) is
// Attribue un événement sur un clic d
// Internet.

class Application is
field dialog: Dialog

// L’application choisit un type de créate


// la configuration actuelle ou des paramè
// d’environnement.
method initialize() is
config = readApplicationConfigFile()

if ([Link] == "Windows") then


dialog = new WindowsDialog()
else if ([Link] == "Web") then
dialog = new WebDialog()
else
throw new Exception("Error! Unknow

// Le code client manipule une instance d’


// concret, mais uniquement au moyen de so
// base. Tant que le client continue de pa
// interface pour manipuler le créateur, v
// n’importe quelle sous-classe du créateu
method main() is
[Link]()
[Link]()

 Possibilités
d’application
 Utilisez la fabrique si vous ne connaissez
pas à l’avance les types et dépendances
précis des objets que vous allez utiliser
dans votre code.

 La fabrique effectue une séparation entre


le code du constructeur et le code qui
utilise réellement le produit. Le code du
constructeur devient ainsi plus évolutif
et indépendant du reste du code.

Par exemple, si vous voulez ajouter un


nouveau produit dans l’application, il
vous suf;t d’ajouter une sous-classe de
création et d’y redé;nir la méthode
fabrique.

 Utilisez la fabrique si vous voulez mettre


à disposition une librairie ou un
framework pour vos utilisateurs avec un
moyen d’étendre ses composants
internes.

 L’héritage est probablement le moyen le


plus simple pour étendre le
comportement par défaut d’une librairie
ou d’un framework. Mais comment le
framework peut-il savoir qu’il doit utiliser
votre sous-classe plutôt qu’un composant
standard ?

La solution est de réunir dans une seule


méthode fabrique le code qui construit
les composants dans le framework, et
non seulement d’étendre ceux-ci, mais de
laisser la possibilité de redé;nir la
méthode fabrique.

Voyons un exemple d’utilisation.


Imaginez la conception d’une application
qui utilise un framework d’UI open
source. Vous désirez utiliser des boutons
ronds, mais le framework ne fournit que
des boutons carrés. Vous étendez le
Bouton standard avec une magni;que

sous-classe BoutonRond . Mais vous devez


à présent expliquer à la classe principale
UIFramework qu’elle doit utiliser la sous-

classe du nouveau bouton plutôt que


celle par défaut.

Pour ce faire, vous créez une sous-classe


UIAvecBoutonsRonds depuis une classe

de base du framework et redé;nissez sa


méthode créerBouton . Même si la
méthode de la classe de base retourne
des Boutons , votre sous-classe renvoie
des BoutonsRonds . Vous pouvez
dorénavant utiliser UIAvecBoutonsRonds
à la place de UIFramework . Et c’est à peu
près tout !

 Utilisez la fabrique lorsque vous voulez


économiser des ressources système en
réutilisant des objets au lieu d’en
construire de nouveaux.

 Le besoin se présente souvent lorsque


l’on utilise des objets qui prennent
beaucoup de ressources tels que des
bases de données, des systèmes de
;chiers ou des ressources réseau.

Que faut-il pour réutiliser un objet


existant ?

1. Tout d’abord, vous devez créer un


moyen de stockage a;n de garder la
trace de tous les objets créés.

2. Lorsqu’un nouvel objet est demandé,


le programme doit chercher un objet
libre dans cette réserve.

3. … et le renvoyer au code client.

4. Si aucun objet n’est disponible, le


programme en crée un nouveau (et
l’ajoute à la réserve).

Cela représente un paquet de code ! De


plus, il faut tout mettre au même endroit
a;n de ne pas polluer le code avec des
doublons.

Il serait probablement plus pratique de


l’écrire dans le constructeur de la classe
de l’objet que l’on veut réutiliser, mais par
dé;nition, un constructeur doit toujours
renvoyer de nouveaux objets. Il ne peut
pas retourner des instances existantes.

C’est pourquoi vous devez disposer d’une


méthode non seulement capable de
créer de nouveaux objets, mais aussi de
réutiliser ceux qui existent déjà. Cela
ressemble énormément à un patron de
conception fabrique.

 Mise en œuvre
1. Implémentez la même interface pour tous
les produits. Cette interface doit déclarer
des méthodes que tous les produits
peuvent avoir en commun.

2. Ajoutez une méthode fabrique vide à


l’intérieur de la classe créateur. Le type de
retour de la méthode doit correspondre à
l’interface commune des produits.

3. Localisez toutes les références aux


constructeurs des produits dans le code
du créateur. Remplacez-les une par une
par des appels à la méthode fabrique et
déplacez le code de la création de
produits dans la méthode fabrique.

Vous allez peut-être devoir ajouter un


paramètre temporaire à la méthode
fabrique pour véri;er le type du produit
retourné.

À ce stade, le code de la méthode fabrique


peut paraître désordonné. Il pourrait
même contenir un gros switch qui choisit
la classe à instancier. Ne vous inquiétez
pas, tout va bientôt rentrer dans l’ordre.

4. Pour chaque type de produit listé dans la


méthode fabrique, créez une sous-classe
de Créateur. Redé;nissez la méthode
fabrique dans les sous-classes et
récupérez les morceaux de code
appropriés de la méthode de base.

5. S’il y a trop de types de produits et peu


d’intérêt de créer des sous-classes pour
tous, vous pouvez réutiliser le paramètre
de contrôle de la classe de base dans les
sous-classes.

Imaginons la hiérarchie de classes


suivante : la classe de base Courrier avec
les sous-classes CourrierAérien et
CourrierTerrestre ; les classes de

Transport sont Avion , Camion et Train .

La classe CourrierAérien n’utilise que des


Avions et la classe CourrierTerrestre

peut utiliser à la fois des Camions et des


Trains . Vous pouvez créer une nouvelle

sous-classe ( CourrierFerroviaire par


exemple) pour gérer les deux cas, mais il y
a une autre possibilité. Le code client peut
passer un argument à la méthode
fabrique du CourrierTerrestre pour
désigner le type de produit qu’elle veut
recevoir.

6. Si après tous ces changements la


méthode fabrique de base est devenue
complètement vide, vous pouvez la rendre
abstraite. S’il reste encore quelques lignes,
vous pouvez y laisser un comportement
par défaut.

 Avantages et
inconvénients
 Vous désolidarisez le Créateur des
produits concrets.

 Principe de responsabilité unique. Vous


pouvez déplacer tout le code de création
des produits au même endroit,
permettant ainsi une meilleure
maintenabilité.

 Principe ouvert/fermé. Vous pouvez


ajouter de nouveaux types de produits
dans le programme sans endommager
l’existant.
 Le code peut devenir plus complexe
puisque vous devez introduire de
nombreuses sous-classes pour la mise en
place du patron. La condition optimale
d’intégration du patron dans du code
existant se présente lorsque vous avez
déjà une hiérarchie existante de classes
de création.

 Liens avec les autres


patrons
La Fabrique est souvent utilisée dès le
début de la conception (moins
compliquée et plus personnalisée grâce
aux sous-classes) et évolue vers la
Fabrique abstraite, le Prototype, ou le
Monteur (ce dernier étant plus mexible,
mais plus compliqué).

Les classes Fabrique abstraite sont


souvent basées sur un ensemble de
Fabriques, mais vous pouvez également
utiliser le Prototype pour écrire leurs
méthodes.

Vous pouvez utiliser la Fabrique avec


l’Itérateur pour permettre aux sous-
classes des collections de renvoyer
différents types d’itérateurs compatibles
avec les collections.

Le Prototype n’est pas basé sur l’héritage,


il n’a donc pas ses désavantages. Mais le
prototype requiert une initialisation
compliquée pour l’objet cloné. La Fabrique
est basée sur l’héritage, mais n’a pas
besoin d’une étape d’initialisation.

La Fabrique est une spécialisation du


Patron de méthode. Une fabrique peut
aussi faire of;ce d’étape dans un grand
patron de méthode.

 Exemples de code

Vous aimerez peut-être aussi