Hypothèse: On N'a Jamais Entendu Parler Du Factory

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 23

PizzaStore :

Un PizzaStore dépendant (18/37)


 Hypothèse: On n’a jamais entendu parler du factory
 Compter le nombre d’objets de pizzas concrètes dont cette classe dépend
 Refaire le compte si on ajoute des pizzas de style bizertin
public class DependentPizzaStore {
Pizza createPizza(String style, String type) {
Pizza pizza=null;
if (style.equals("Sfax")){ Gérer toutes les pizzas de
if (type.equals("cheese"){
pizza=new SfaxStyleCheesePizza();
style sfaxien
} else if (type.equals("pepperoni"){
pizza=new SfaxStylePepperoniPizza();
} else if (type.equals("clam"){
pizza=new SfaxStyleClamPizza();
}
} else if (style.equals("Tunis")){
if (type.equals("cheese"){ Gérer toutes les pizzas de
pizza=new TunisStyleCheesePizza(); style tunisois
} else if (type.equals("pepperoni"){
pizza=new TunisStylePepperoniPizza();
} else if (type.equals("clam"){
pizza=new TunisStyleClamPizza();
}
} else {System.out.println("Erreur: type de pizza invalide");}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
98 }
}
PizzaStore :
La dépendance entre les objets (19/37)
 Cette version de PizzaStore dépend de tous les objets pizzas parce qu’elle les crée
directement
 On dit que PizzaStore dépend des implémentations des pizzas parce que chaque
changement des implémentations concrètes des pizzas, affecte le PizzaStore
Si les implémentations des pizzas
changent, on doit modifier PizzaStore

Pour chaque nouveau type de pizza,


on ajoute une autre dépendance dans
la méthode create()
99
PizzaStore :
L’inversion de dépendance (20/37)
 Réduire les dépendances aux classes concrètes dans notre code,
est une "bonne chose"
 Le principe qui formalise cette notion s’appelle "principe
d’inversion de dépendance" :
 Règle 5: Dépendre des abstractions. Ne jamais dépendre
de classes concrètes.
 Ce principe prétend que nos "haut-niveau" composants ne
doivent pas dépendre de nos "bas-niveau" composants; plutôt, les
deux doivent dépendre des abstractions.
 Un composant de haut-niveau (PizzaStore) est une classe dont le
comportement dépend des autres composants de bas-
niveau(Pizza)

100
PizzaStore :
Appliquons ce principe (21/37)
PizzaStore dépend seulement de
Pizza, qui est une classe abstraite
Pizza est une classe
abstraite.. abstraction
Les classes de pizzas concrètes dépendent
aussi de l’abstraction Pizza, parce qu’elles
implémentent l’interface Pizza

Le "Factory Method"
est la technique la plus
puissante d’adhérence
au principe d’inversion
de dépendance, mais
pas la seule...

101
PizzaStore :
Les ingrédients des pizzas (22/37)
 Problème : quelques franchises n’ont pas utilisé la
même procédure de préparation, et ce en substituant
des ingrédients par d’autres de basse qualité, afin
d’augmenter leur marge.
! Il faut assurer la consistance des ingrédients

 Solution : créer un factory qui produit les ingrédients,


et les transporter aux franchises
 Le seul problème avec ce plan : Ce qui est sauce rouge
à Sfax, n’est pas sauce rouge à Tunis
 Il y a un ensemble d’ingrédients à transporter à Sfax, et un
autre ensemble à transporter à Tunis
102
PizzaStore :
Les menus des pizzas (23/37)

Sfax Tunis
Pizza Menu Pizza Menu
Nous avons les mêmes
Cheese Pizza Cheese Pizza
Sauce marinara, Parmesan,
familles de produits, mais
différente implémentations Sauce tomate prune, Mozzarella,
Emmental Roquefort
selon la région
Clam Pizza Clam Pizza
Sauce marinara, Parmesan, Sauce tomate prune, Mozzarella,
Clovis, Olive verte Palourde, Olive noire
Pepperoni Pizza Pepperoni Pizza
Sauce marinara, Parmesan, Sauce tomate prune, Mozzarella,
Aubergine, Poivron, Olive verte Épinard, Poivre, Olive noire

103
PizzaStore :
Les familles des ingrédients (24/37)
Chaque famille correspond à un Tunis
type de sauce, un type de
fromage, un type de légume, et un PlumTomatoSauce
Mozzarella
type d’olive (et d’autres types)

Spinach
BlackOlive

Sfax
MarinaraSauce
Parmesan

Toutes les PizzaStores utilisent


Eggplant les mêmes composants, mais
GreenOlive
chaque région possède une
implémentation spécifique de ces
composants

104
PizzaStore :
Les factories des ingrédients (25/37)
 Le factory est le responsable de la création de la pâte, la sauce,
le fromage, etc.
Pour chaque ingrédient, on
public interface PizzaIngredientFactory {
crée une create() méthode
Dough createDough();
dans notre interface
Sauce createSauce();
Cheese createCheese();
Veggies[] createVeggies();
Clam createClam();
} Beaucoup de nouvelles
classes, une par ingredient
 A faire :
 Construire un facotry pour chaque région: une sous-classe de
PizzaIngredientFactory qui implémente chaque create() méthode
 Implémenter un ensemble de classes d’ingrédients, à utiliser par les
factories tels que: OliveVerte, Mozzarella, SauseMarinara, etc.
 Lier ceci avec notre ancien code de PizzaStore, tout en travaillant
nos factories d’ingrédients
105
PizzaStore :
Les factories de Sfax (26/37)

public class SfaxPizzaIngredientFactory implements PizzaIngredientFactory


{
public Dough createDough(){
return new ThinDough(); Pour chaque famille d’ingrédient, on
} crée la version sfaxienne
public Sauce createSauce(){
return new MarinaraSauce();
}
public Cheese createCheese(){
return new Parmesan();
}
public Veggies[] createVeggies(){
Veggies veggies[]={new Garlic(), new Onion(), new EggPlant()};
return veggies;
}
public Clam createClam(){
return new Clovis();
} Palourde() pour le
} cas de tunis
106
PizzaStore :
Retravaillons la classe Pizza (27/37)

public abstract class Pizza { Les ingrédients d’une paizza


String name; (liste non-exhaustive)
Dough dough;
Sauce sauce;
La collecte des ingrédients se fait dans cette
Cheese cheese;
méthode (à travers un factory d’ingrédients)
Veggies veggies[];
qui sera définie par les classes dérivées
Clam clam;
abstract void prepare();
void bake(){
System.out.println("Cuire durant 25mn à 350°");}
void cut(){
System.out.println("Couper en morceaux à la diagonale");}
void box(){
System.out.println("Placer la pizza dans un boitier officiel");}
void setName(String s){
name=s;}
String getName(){ Les autres méthodes sont les
return name;} mêmes (à l’exception de prepare())
}
107
PizzaStore :
Retravaillons les classes des Pizzas (28/37)
Pour faire la pizza, on besoin d’un
factory. Chaque classe Pizza prend le
factory à travers son constructeur

public class CheesePizza extends Pizza {


PizzaIngredientFactory ingredientfactory;
CheesePizza(PizzaIngredientFactory ingredientfactory){
this.ingredientfactory = ingredientfactory;
}
void prepare(){
System.out.println("Préparons " + name);
dough = ingredientfactory.createDough();
sauce = ingredientfactory.createSauce();
cheese = ingredientfactory.createCheese();
}

} Chaque fois que la méthode prepare()


a besoin d’ingrédient, elle appelle le
factory pour le produire

108
PizzaStore :
Retravaillons les classes des Pizzas (29/37)

Un factory pour chaque type de Pizza

public class ClamPizza extends Pizza {


PizzaIngredientFactory ingredientfactory;
ClamPizza(PizzaIngredientFactory ingredientfactory){
this.ingredientfactory = ingredientfactory;
}
void prepare(){
System.out.println("Préparons " + name);
dough = ingredientfactory.createDough();
sauce = ingredientfactory.createSauce();
cheese = ingredientfactory.createCheese();
clam= ingredientfactory.createClam();
} Pour faire une ClamPizza, la méthode
prépare les ingrédients
} correspondants de son factory local.
Si c’est le factory de sfax, on
va préparer des clovis

109
PizzaStore :
Retravaillons les PizzaStores (30/37)
Le store de Sfax est composé d’un
factory sfaxien d’ingrédients/
public class SfaxPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
Pizza pizza = null;
PizzaIngredientFactory ingredientfactory=
new SfaxPizzaIngredientFactory();
On passe à chaque pizza le factory
if (item.equals("cheese")){ censé créer ses ingrédients
pizza = new CheesePizza(ingredientfactory);
pizza.setName("Sfax Style Cheese Pizza");
} else if (item.equals("pepperoni")){
pizza = new PepperoniPizza(ingredientfactory);
pizza.setName("Sfax Style Pepperoni Pizza");
} else if (item.equals("clam")){
pizza = new ClamPizza(ingredientfactory);
pizza.setName("Sfax Style Clam Pizza");
}
return pizza;
}
}
110
PizzaStore :
Factories (31/37)
Définit l’interface

Offre les
Abstract Ingredient Factory
implémentations
des ingrédients

Sfax Tunis

De l’abstract factory, on dérive


plusieurs concrets factories qui
produisent les mêmes produits, mais avec
différentes implémentations
En passant (au constructeur) une variété
de factories, on obtient une variété
d’implémentations, tout en gardant le
même code du client
111
PizzaStore :
Commander des pizzas (32/37)
Je voudrai une pizza Je voudrai une pizza
de grande taille avec beaucoup de taille moyenne avec
de fromage du style peu de fromage et au thon
tunisien du style sfaxien

PizzaStore tunisps = PizzaStore sfaxps =


new TunisPizzaStore(); new SfaxPizzaStore();

Instance du store spécifique

Prendre des commandes

tunisps.orderPizza("cheese"); sfaxps.orderPizza("cheese");

C’est une méthode de l’instance tunisps (respectivement


sfaxps), définie dans la classe PizzaStore
112
PizzaStore :
Commander des pizzas (33/37)
tunisps.orderPizza("cheese"); sfaxps.orderPizza("cheese");

La méthode orderPizza() appelle initialement createPizza()

Pizza pizza= createPizza("cheese"); Pizza pizza= createPizza("cheese");

La méthode createPizza() implique le factory d’ingrédients


Pizza pizza= new Pizza pizza= new
CheesePizza(tunisIngeredientFactory); CheesePizza(sfaxIngeredientFactory);

Chaque instance de pizza est associée à un factory d’ingrédients

La méthode prepare() est appelée et chaque factory est appelé pour produire les
ingrédients de la région

void prepare(){ void prepare(){

113 CheesePizza à la tunisoise CheesePizza à la sfaxienne


PizzaStore :
Commander des pizzas (34/37)
void prepare(){ void prepare(){
dough = factory.createDough(); dough = factory.createDough();
// Pâte coustillante // Pâte mince
sauce = factory.createSauce(); sauce = factory.createSauce();
// Sauce tomate prune // Sauce marinara
cheese = factory.createCheese(); cheese = factory.createCheese();
// Mozzarella, Roquefort // Parmesan, Emmental
} }
Elle prépare une pizza au Elle prépare une pizza au
fromage avec les ingrédients fromage avec les ingrédients
du style tunisien du style sfaxien
On termine la création
pizza.bake(); pizza.bake();
pizza.cut(); pizza.cut();
pizza.box(); pizza.box();

114
De style tunisien De style sfaxien
PizzaStore :
Le patron Abstract Factory (35/37)

 Définition: Abstract Factory


 Le patron abstract factory offre une interface de
création de familles d’objets dépendants (en relation), sans
spécifier leurs classes concrètes.

115
PizzaStore :
Le diagramme de classes du patron (36/37)
Le client est composé au moment de
l’exécution par un factory concret
L’abstract factory définit un Client
ensemble de méthodes pour la
production des produits Une famille de produits
<<interface>>
AbstractProductA
<<interface>>
AbstractFactory
createProductA()
createProductB()
ProductA2 ProductA1

<<interface>>
AbstractProductB

ConcretFactory1 ConcretFactory2
createProductA() createProductA()
createProductB() createProductB() ProductB2 ProductB1
Les factories concrets implémentent les
différences familles de produits
116
PizzaStore :
La conception finale (37/37) Les clients de l’abstract factory
sont les stores de Sfax et de Tunis
SfaxPizzaStore
L’abstract factory définit un <<interface>>
l’ensemble des produits qu’on a Clam
besoin pour faire une pizza

<<interface>> Clovis Palourde


PizzaIngredientFactory
createSauce() <<interface>>
createCheese() Sauce
createClam()
//etc.

MarinaraSauce PlumTomatoSauce

TunisPizzaIngred SfaxPizzaIngredi <<interface>>


ientFActory entFactory Cheese
createSauce() createSauce()
createCheese() createCheese()
createClam() createClam()
Parmesan Mozzarella
La tâche des factories est de produire les
ingrédients spécifiques à chaque région
117 Chaque factory produit différent implémentation
de chaque famille de produits
Récapitulatif (1/2)
 Bases de l’OO: Abstraction, Encapsulation, Polymorphisme & Héritage
 Principes de l’OO
 Encapsuler ce qui varie
 Favoriser la composition sur l’héritage
 Programmer avec des interfaces et non des implémentations
 Opter pour une conception faiblement couplée
 Les classes doivent être ouvertes pour les extensions et fermées pour les
modifications
 Dépendre des abstractions. Ne jamais dépendre de classes concrètes
 Patron de l’OO
 Strategy: définit une famille d’algorithmes interchangeables
 Observer: définit une dépendance1-à-plusieurs entre objets.
 Decorator: attache des responsabilités additionnelles à un objet dynamiquement.
 Factory Method: définit une interface de création des objets, et laisse les
classes-dérivées décider de la classe de l’instanciation.
 Abstract Factory: offre une interface de création de familles d’objets
dépendants, sans spécifier leurs classes concrètes
118
Récapitulatif (2/2)
 Tous les factories encapsule la création des objets
 Malgré qu’il n’est un vrai patron, le "Simpe Factory" est une manière simple
de découplage de clients des concrètes classes
 Factory Method repose sur l’héritage: La création d’objet est déléguée aux
sous-classes qui implémentent la méthode factory de création d’objets
 Abstract Factory repose sur la composition d’objets: La création d’objet est
implémentée dans une méthode exposée dans l’interface du factory
 Tous les patrons factories soutiennent le faible couplage entre notre
application et les classes concrètes.
 L’intension de Factory Method est de permettre à une classe de reporter
l’instanciation à ses sous-classes.
 L’intension d’Abstract Factory est de créer une famille d’objets en relation
sans dépendre de leurs classes concrètes
 L’inversion de dépendance nous guide afin d’éviter les dépendances des
classes concrètes, et s’efforcer pour les abstractions
 Factories sont des techniques puissantes de codages des abstractions et non
des classes concrètes
119
Exercice
 Ecrire la classe abstraite Automobile
caractérisée par un modèle, une couleur,
une puissance et un espace. Ajouter une
méthode afficherCaractéristiques().
 Ecrire les classes AutomobileElectricité
et AutomobileEssence.
 Ecrire la classe abstraite Scooter
caractérisée par un modèle, une couleur
et une puissance. Ajouter une méthode
afficherCaractéristiques().
 Ecrire les classes ScooterElectricité et
ScooterEssence.
 Ecrire l’interface FabriqueVéhicule
permettant de créer des Automobiles et
des Scooters
 Ecrire les classes
FabriqueVéhiculeElecticité et
FabriqueVéhiculeEssence réalisant
FabriqueVéhicule
120

Vous aimerez peut-être aussi