22
Stéphane Gobron HESSO – HEArc – ISIC 2015 Design Patterns Où en sommesnous? Plan de cours Ch.1 : OORappels Ch.2 : Etude de cas => le bridge DP Ch.3 : Conceptualisation, Singleton et Composite DPs Ch.4 : Decorator, State, Prototype, Proxy et Builder DPs Ch. 5 : Factory, Abstract factory, Observer, Commande, Memento DPs Mots clés du cours

BSc2 DesignPatterns chap4 v1-31 - stephane-gobron.net€¦ · Design Patterns 4.2 «State» pattern Contexte, définition

Embed Size (px)

Citation preview

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®