Stéphane GobronHES‐SO – HE‐Arc – ISIC
2015
Design Patterns
Où en sommes‐nous?
Plan de cours
Ch.1 : OO‐Rappels
Ch.2 : Etude de cas => le bridge DP
Ch.3 : Conceptualisation, Singleton et CompositeDPs
Ch.4 : Decorator, State, Prototype, Proxy et Builder DPs
Ch. 5 : Factory, Abstract factory, Observer, Commande, Memento DPs
Mots clés du cours
Design Patterns
Cinq nouveaux patrons de conception
Decorator, State, Prototype, Proxy et Builder
Decorator
State
Prototype
Proxy
Builder
Tante Thomson
Clark,le nouvel homme Danny, le maçon
Bart‐27726
Betty,dans tous ces états
Chapitre 44.1 « Decorator »
les bons concepteurs se méfient de l’héritage
Chez Starbuzz Coffee Propriétés Exemples d’applications Structure générale Annexe
Tête la première Design Patterns,
E. F
reem
an & E. F
reem
an, E
dition O
’REILY®
Clark,le nouvel homme
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
« Starbuzz, l’autre coût du café »
Coût d’un café Ne pas confondre avec une marque non moins célèbre!
Starbuzz Coffee vend de nombreuses boissons à base de café et leurs coûts est calculé différemment. Exemples de breuvage : HouseBlend, DarkRoast, Décaféiné, Espresso…
Starbuzz a besoin d'un système pour calculer le coût de chaque boisson lorsque les achats sont effectués.
Dessinons un diagramme de classe pour le système!
Starbuzz Coffee vend de nombreuses boissons à base de café et leurs coûts est calculé différemment. Exemples de breuvage : HouseBlend, DarkRoast, Décaféiné, Espresso…
Starbuzz a besoin d'un système pour calculer le coût de chaque boisson lorsque les achats sont effectués.
Dessinons un diagramme de classe pour le système!
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
Faire le schéma de classe UML pour les cafés suivants : HouseBlend DarkRoast Décaféiné Espresso
Attributs Description
Méthodes getDescription() Cost()
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
Les boissons de base
HouseBlend__________
cost()
HouseBlend__________
cost()
DarkRoast__________
cost()
DarkRoast__________
cost() Décaféiné__________
cost()
Décaféiné__________
cost()
Espresso__________
cost()
Espresso__________
cost()
Brevage_____________description_____________getDescription()cost()
Brevage_____________description_____________getDescription()cost()
Jusque là tout va bien…
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
Il y a des options à ajouter!
Solution 1
Spécialisons les classes pour chacune des combinaisons possibles
Starbuzz propose aussi de nombreuse options telles que caramel, sucre, lait, crème, chocolat, chantilly…
Dessinons le nouveau diagramme de classe
Starbuzz propose aussi de nombreuse options telles que caramel, sucre, lait, crème, chocolat, chantilly…
Dessinons le nouveau diagramme de classe
Brevage_____________description_____________getDescription()cost()
Brevage_____________description_____________getDescription()cost()
HouseBlend_andMilk
__________cost()
HouseBlend_andMilk
__________cost()
HouseBlend_andCaramel__________
cost()
HouseBlend_andCaramel__________
cost()
HouseBlend_andSugar__________
cost()
HouseBlend_andSugar__________
cost()
……Nombre de combinaison gigantesque!
Solution inenvisageable!!
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
Solution 2
Spécialisons la classe mère
Brevage_____________description
hasMilk()hasCaramel()hasSugar()…_____________getDescription()cost()
Brevage_____________description
hasMilk()hasCaramel()hasSugar()…_____________getDescription()cost()
HouseBlend__________
cost()
HouseBlend__________
cost()
DarkRoast__________
cost()
DarkRoast__________
cost()
Décaféiné__________
cost()
Décaféiné__________
cost()
……
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
Solution 2
Spécialisons la classe mère
ATTENTION AUX PROBLEMES !!!
Conception rigide et difficilement maintenable!
Cette solution entraîne les problèmes suivants
• Trop de sous‐classes nécessaires• Nécessité de définir la mise en œuvre de chaque
sous‐classe• Toutes les classes héritent d'un comportement
statique => modification difficile• Le comportement hérité ne peut pas être modifié à
l'exécution, à savoir le comportement est statique lors de l'exécution.
Cette solution entraîne les problèmes suivants
• Trop de sous‐classes nécessaires• Nécessité de définir la mise en œuvre de chaque
sous‐classe• Toutes les classes héritent d'un comportement
statique => modification difficile• Le comportement hérité ne peut pas être modifié à
l'exécution, à savoir le comportement est statique lors de l'exécution.
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
L’idée!
Prix total
Exemple pratique
Si on choisi : un café Dark Roast avec les options Mocha et fouetté –Whipped
Exemple pratique
Si on choisi : un café Dark Roast avec les options Mocha et fouetté –Whipped
Commencons par l’objet DarkRoastCommencons par l’objet DarkRoast
cost()DarkRoast
cost()Mocha
Enveloppons l’objetMochaEnveloppons l’objetMocha
cost()Whip
Enveloppons l’objetWhipEnveloppons l’objetWhip
Calculons le prix!Calculons le prix!
0.990.2+0.99
0.1+0.2+0.99
Design Patterns
4.1 «Decorator»
Chez Starbuzz Coffee
Starbuzz Coffee : avec les options
La solution
Un systèmerécursif
Design Patterns
4.1 «Decorator»
Propriétés
Créer des augmentations dans les traitements sans utiliserle mécanisme d’héritage
Applicable principalement dans les cas où les énumérationssont larges et/ouimprévisibles
Patron de conception “Décoration”
Patron de type StructurePatron de type Structure
Design Patterns
4.1 «Decorator»
Exemples d’applications
Fichier –Affichage, décoration
Hamburger – Calcul de prix, décoration
1..1
Design Patterns
4.1 «Decorator»
Structure générale
1..1
Design Patterns
4.1 «Decorator»
Annexe
Propriété principale
Enveloppe un objet pour fournir un nouveau comportement
http://w
ww.curtis.la
ssam
.net/
Chapitre 44.2 « State » pattern
l’état des choses
Contexte / définition Exemples d’applications Structure générale
Tête la première Design Patterns,
E. F
reem
an & E. F
reem
an, E
dition O
’REILY®
Betty,dans tous ses états
Design Patterns
4.2 « State » pattern
Contexte, définition
Des objets peuventavoir un comportementqui dépend de leur étatou de leur statut
Solution permettant un découplage entre les
traitements et l’étatspar rapport au client
d’ajouter facilementdes états
de modifier le comportement d’un état sans conséquencepour les autres
Patron de type ComportementPatron de type Comportement
Design Patterns
4.2 « State » pattern
Exemples d’applications
Intelligence artificielledans les jeux : e.g. celled’un agent
Fenêtre dans uneapplication graphique
Exemple de changement d’état d’une banque – classequi a plusieurs agence – objets
• Une banqueplusieurs agencesCertaines ouvrentCertaines fermes
Evidemment uneagence fermée sera forcément ouverte à un autre moment
Design Patterns
4.2 « State » pattern
Exemple d’application
La banque
l'abstraction des «comportements» de la banque
l'abstraction des «comportements» de la banque
l'interfaçage avec le reste de son contexte
l'interfaçage avec le reste de son contexte
Design Patterns
4.2 « State » pattern
Structure générale
Deux classes principales :
la classe State (état), qui définit l'abstraction des comportements du patron
la classe Context, qui s'occupe de l'interfaçage du patron avec le reste de son contexte, i.el'application, le «client»
http://fr.wikipedia.org/wiki/%C3%89tat_(patron_de_conception)
La classe State permet via ses spécialisations de créer et gérer dynamiquement les comportements dont l'application aura besoin
La classe State permet via ses spécialisations de créer et gérer dynamiquement les comportements dont l'application aura besoin
Context
+request()
state.handle()
State
+handle()
ConcreteStateA
+handle()
ConcreteStateB
+handle()
Client
Chapitre 44.3 « Prototype »
en cas de création coûteuse ou complexe
Contexte et définition Cas d’utilisation Exemple Structure générale
Multiplication virtuelle à moindre coût
Bart‐27726, c’est lui!
Ne pas confondre avec Bart‐27725, rien à voir…
Design Patterns
4.3 « Prototype »
Contexte et définition
Créer un nouvel objet en se basant sur un objet existant
Éviter la charge de création du nouvelobjet
Remplacer cettecharge de création par l’adaptation d’unecopie l’existante
Cas d’utilisation
Patron utile uniquement dans le cas où la créationest beaucoup plus coûteuse que l’adaptation
Cas d’utilisation
Patron utile uniquement dans le cas où la créationest beaucoup plus coûteuse que l’adaptation
Patron de type CréationPatron de type Création
Design Patterns
4.3 « Prototype »
Exemples
Nouveau résultat de requête dans une BDD distante
Objet nécessitantdiverses négociations–e.g. requite Internet –pour être créé
Exemple d’application
Structure générale
operation()
Client
clone()
ConcretePrototype1
clone()
ConcretePrototype2
clone()
«interface»Prototype
return copy of selfthis in C++
Object p = prototype.clone();
«import»I
return copy of selfthis in C++
Chapitre 44.4 « Proxy »
Propriété / utilisation Deux exemples Structure générale
MelleThomson,Profession : Proxy
Design Patterns
4.4 « Proxy »
Métaphore conceptuelle
Proxy au travers de la pratique du mariage arrangé
Une personne intermédiaire qui représente une autre personne… une personne très spéciale
Mari potentiel
Tante de lafutur mariée
Potentielle future mariée
MelleThomson, la tante
MelleThomson,La jeune femme
Design Patterns
4.4 « Proxy »
Propriété / utilisation
Un objet très spécial Il représente un objet!
On utilise le patron de conception proxyquand…
…on souhaite avoir un représentant d’un objet…
…mais pas l’objet lui‐même
Patron de type StructurePatron de type Structure
Design Patterns
4.4 « Proxy »
2 exemples d’utilisation
1. un objet très coûteux en temps à créer –attention, ne pas confondre avec le DP prototype
2. un objet très peu sécurisé
Avoir seulement un représentant de ces objets est intéressant
l’objet «coûteux» – e.g. une immense BDD—«existe» avec son proxy avec une allocation minime
l’objet peu sécurisé devient protégé par sa représentation proxy
http://w
ww.curtis.la
ssam
.net/
or
Design Patterns
4.4 « Proxy »
Deux exemples
1. Expensive proxy2. Secure proxy
Propriété OO majeure encapsule un objet en contrôle l’accès
http://w
ww.curtis.la
ssam
.net/
Design Patterns
4.4 « Proxy »
Structure générale
Schéma UML
http://w
ww.youtube.co
m/w
atch
?v=Mfd25
VlzulY&feature=en
dscreen
Chapitre 44.5 « Builder »
Propriétés Cas d’utilisation Exemple concert Structure générale Annexe : Code PizzaBuilder
Danny le maçon
Design Patterns
4.5 «Builder»
Propriétés
Idée/principe
Séparer
le processus génériquede création d’un objet complexe
des détails de contruction de sescomposants
Patron de type CréationPatron de type Création
Permettre de créer divers type d’objetscomplexes à partir d’un processus de construction commun
Permettre de créer divers type d’objetscomplexes à partir d’un processus de construction commun
Design Patterns
4.5 «Builder»
Cas d’utilisation
Construire des
menus différents maisde mêmes structures
collections de mêmesstructures
Design Patterns
4.5 «Builder»
Exemple concret
Lors de la création d’un menu, il y a toujours
un sandwich un plat à base de
patate une boisson un cadeau
Création d’un menu d’un fastfood
Design Patterns
4.5 «Builder»
Structure générale
Design Patterns
4.5 «Builder»
Annexe : Code CookPizza
Le cuisinier et le code mainclass Cook {public:
Cook(): pizzaBuilder_(nullptr){ }~Cook() { if (pizzaBuilder_) delete pizzaBuilder_; }
void pizzaBuilder(PizzaBuilder* pizzaBuilder) {if (pizzaBuilder_) delete pizzaBuilder_;pizzaBuilder_ = pizzaBuilder;
}
const Pizza& getPizza() { return pizzaBuilder_‐>pizza(); }
void constructPizza() {pizzaBuilder_‐>buildDough();pizzaBuilder_‐>buildSauce();pizzaBuilder_‐>buildTopping();
}
private:PizzaBuilder* pizzaBuilder_;
};
class Cook {public:
Cook(): pizzaBuilder_(nullptr){ }~Cook() { if (pizzaBuilder_) delete pizzaBuilder_; }
void pizzaBuilder(PizzaBuilder* pizzaBuilder) {if (pizzaBuilder_) delete pizzaBuilder_;pizzaBuilder_ = pizzaBuilder;
}
const Pizza& getPizza() { return pizzaBuilder_‐>pizza(); }
void constructPizza() {pizzaBuilder_‐>buildDough();pizzaBuilder_‐>buildSauce();pizzaBuilder_‐>buildTopping();
}
private:PizzaBuilder* pizzaBuilder_;
};
#include <string>#include <iostream>using namespace std;
int main() {Cook myC;myC.pizzaBuilder(new HawaiianPizzaBuilder);myC.constructPizza();Pizza hawaiian = cook.getPizza();hawaiian.open();myC.pizzaBuilder(new SpicyPizzaBuilder);myC.constructPizza();
Pizza spicy = cook.getPizza();spicy.open();
}
#include <string>#include <iostream>using namespace std;
int main() {Cook myC;myC.pizzaBuilder(new HawaiianPizzaBuilder);myC.constructPizza();Pizza hawaiian = cook.getPizza();hawaiian.open();myC.pizzaBuilder(new SpicyPizzaBuilder);myC.constructPizza();
Pizza spicy = cook.getPizza();spicy.open();
}
Design Patterns
4.5 «Builder»
La pizza
// "Product"class Pizza {public:
void dough(const string& dough) {dough_ = dough;}void sauce(const string& sauce) {sauce_ = sauce;}void topping(const string& topping) {topping_ = topping;}void open() const {
cout << "Pizza with " << dough_ << " dough, " << sauce_ << " sauce and " << topping_ << topping. Mmm." << endl;}
private:string dough_;string sauce_;string topping_;
};
// "Product"class Pizza {public:
void dough(const string& dough) {dough_ = dough;}void sauce(const string& sauce) {sauce_ = sauce;}void topping(const string& topping) {topping_ = topping;}void open() const {
cout << "Pizza with " << dough_ << " dough, " << sauce_ << " sauce and " << topping_ << topping. Mmm." << endl;}
private:string dough_;string sauce_;string topping_;
};
Annexe : Code CookPizza
Design Patterns
4.5 «Builder»
Annexe : Code CookPizza
Le pattern Builder et sa pizza abstraite et deux exemples de pizza concrètes
// "Abstract Builder"class PizzaBuilder {public:
const Pizza& pizza() {return pizza_;}virtual void buildDough() = 0;virtual void buildSauce() = 0;virtual void buildTopping() = 0;
protected:Pizza pizza_;
};
// "Abstract Builder"class PizzaBuilder {public:
const Pizza& pizza() {return pizza_;}virtual void buildDough() = 0;virtual void buildSauce() = 0;virtual void buildTopping() = 0;
protected:Pizza pizza_;
};
class SpicyPizzaBuilder : public PizzaBuilder {public:
void buildDough() {pizza_.dough("pan baked");}void buildSauce() {pizza_.sauce("hot");}void buildTopping()pizza_.topping("pepperoni+salami");}
};
class SpicyPizzaBuilder : public PizzaBuilder {public:
void buildDough() {pizza_.dough("pan baked");}void buildSauce() {pizza_.sauce("hot");}void buildTopping()pizza_.topping("pepperoni+salami");}
};
class HawaiianPizzaBuilder : public PizzaBuilder {public:
void buildDough() {pizza_.dough("cross");}void buildSauce() {pizza_.sauce("mild");} void buildTopping() {pizza_.topping("ham+pineapple");}
};
class HawaiianPizzaBuilder : public PizzaBuilder {public:
void buildDough() {pizza_.dough("cross");}void buildSauce() {pizza_.sauce("mild");} void buildTopping() {pizza_.topping("ham+pineapple");}
};
Composite Decorator State
Design Patterns
Labo 3 : tâche 1/3
Composite DP
Partons d’une classe Fruit caractérisé par
<string> nom du fruit
<bool> Pepin ‐‐qui indique si le fruit contient ou pas des pépins
Méthodes AfficherFruit et AvecOuSansPepin
Enoncé
Nous souhaitons être capable de gérer des Paniers‐de‐fruitNotez qu’un panier de fruits est un produit composé de plusieurs Fruit
Utiliser le patron « Composite » pour gérer de manière identique et encapsulée les Fruit et les Paniers‐de‐Fruit
• Concernant la méthode AfficherFruit de Panier‐de‐Fruit, suivez ce format –par exemple un panier contenant une banane, une pomme et deux fraise : «Panier [Banane, Pomme, Fraise, Fraise]»
• Pour la caractéristique « avec ou sans pépins », il s’agit de voir si au moins un des fruits est avec pépin ; dans l’exemple, le panier est « Avec pépin » sinon, si aucun fruit n’a de pépin, le panier sera « Sans pépin »
Design Patterns
Labo 3 : tâche 2/3
Decorator DP
Étendre dynamiquement le comportement de la classe Fruit
Enoncé
L’affichage des informations d’un Fruit ou d’un Panier doit être décoré avec des « * », la méthode AfficherFruit donnera sur console :
******************************Banane – Sans pépin******************************
Implémenter dans la classe Client principale, la possibilité de demander au client le type d’affichage souhaité‐ L’affichage simple n’ajoute aucune décoration‐ L’affichage décoré permet de choisir entre trois caractères
de décoration différents : « * » , « # » , ou « = »‐ Vous devez utiliser pour cela le patron de conception
« Décorateur » pour étendre dynamiquement le comportement de la méthode AfficherFruit
Design Patterns
Labo 3 : tâche 3/3
State DP
Créer une classe Commande ayant une méthode appelé TraiterCommande
Cette méthode admet trois comportements différents
En attente Payée Envoyée
Compresser les trois tâches sous forme de trois projets développés en C++ sous CodeBlock dans un fichier au format suivant :« Lab3_equipe#_noms.{zip/7z/…}»
Enoncé
‐ En attente : dans ce cas, TraiterCommande n’affiche rien, et change le statut de la commande à « payée »
‐ Payée : dans ce cas, TraiterCommande affiche un message pour annoncer que la commande a été traitée et change le statut de la commande à « Envoyée »
‐ Envoyé : dans ce cas, TraiterCommande affiche un message pour annoncer que la commande a été envoyée
Initialement, une commande est en attente
Il s’agit d’utiliser le patron « State » pour gérer les états d’une commande, ainsi que les changements d’états possibles pour une commande
Merci! Questions?
Prochain chapitre :De la factory à l’Iterator
Factory Abstract factory Observer Command Memento
Tête la première Design Patterns,
E. F
reem
an & E. F
reem
an, E
dition O
’REILY®