cours design pattern m youssfi partie 3 decorateur

30
Design Patterns Design Patterns Part 3 Part 3 Mohamed Youssfi [email protected] Mohamed Youssfi Laboratoire Signaux Systèmes Distribués et Intelligence Artificielle (SSDIA) ENSET, Université Hassan II Casablanca, Maroc Email : [email protected] Supports de cours : http://fr.slideshare.net/mohamedyoussfi9 Chaîne vidéo : http://youtube.com/mohamedYoussfi Recherche : http://www.researchgate.net/profile/Youssfi_Mohamed/publications

Upload: mohamed-youssfi

Post on 08-Jul-2015

1.545 views

Category:

Software


101 download

DESCRIPTION

Design Pattern Decorator

TRANSCRIPT

Page 1: Cours design pattern m youssfi partie 3 decorateur

Design PatternsDesign PatternsPart 3Part 3

Mohamed Youssfi

[email protected]

Mohamed Youssfi

Laboratoire Signaux Systèmes Distribués et Intelligence Artificielle (SSDIA)

ENSET, Université Hassan II Casablanca, Maroc

Email : [email protected]

Supports de cours : http://fr.slideshare.net/mohamedyoussfi9

Chaîne vidéo : http://youtube.com/mohamedYoussfi

Recherche : http://www.researchgate.net/profile/Youssfi_Mohamed/publications

Page 2: Cours design pattern m youssfi partie 3 decorateur

Pattern DécorateurPattern Décorateur

Page 3: Cours design pattern m youssfi partie 3 decorateur

Pattern DécorateurPattern Décorateur

� Catégorie :◦ Structure

� Définition du pattern Décorateur ◦ Le pattern Décorateur attache dynamiquement des

responsabilités supplémentaires à un objet. Il fournit responsabilités supplémentaires à un objet. Il fournit une alternative souple à la dérivation, pour étendre les fonctionnalités.

� Résultat :◦ Le Design Pattern permet d'isoler les

responsabilités d'un objet.

[email protected]

Page 4: Cours design pattern m youssfi partie 3 decorateur

Diagramme de classesDiagramme de classesChaque composant peut être

utilisé seul ou enveloppé par

un décorateurChaque Décorateur A-UN

Enveloppe un composant, ce qui signifie qu’il a une variable

d’instance qui contient une référence à un composant.

Les décorateurs implémentent la même

interface ou classe abstraite que le composant

qu’il vont décorer

Les décorateurs ajoute généralement le nouveau comportement en effectuant

un traitement avant ou après une méthode existante dans le composant

Le composant concret est

un objet auquel, nous

allons ajouter

dynamiquement un

nouveau comportement.

Il dérive de Composant

Page 5: Cours design pattern m youssfi partie 3 decorateur

ResponsabilitésResponsabilités� ComposantAbstrait :

◦ Définit l'interface ou une classe abstraite qui représente le composant abstrait à décorer.

� ComposantConcret :

◦ Implémentation de l’interface qui représente le composant concret à décorer et qui correspondant aux fonctionnalités souhaitées à la base.

� DecorateurAbstrait : � DecorateurAbstrait :

◦ Interface ou classe abstraite qui définit le décorateur abstrait et contient une référence vers un objet Abstraction.

� DecorateurConcretImpl1 et DecorateurConcretImpl2 :

◦ Représentent les décorateurs concrets des composants

◦ Les décorateurs ont un constructeur acceptant un objet ComposantAbstrait.

◦ Les méthodes des décorateurs appellent la même méthode de l'objet qui a été passée au constructeur.

◦ La décoration ajoute des responsabilités en effectuant des opérations avant et/ou après cet appel.

[email protected]

Page 6: Cours design pattern m youssfi partie 3 decorateur

ResponsabilitésResponsabilités� La partie cliente manipule un objet Abstraction.

� En réalité, cet objet Abstraction peut être

◦ un objet ComposantConcret

◦ ou un objet DecorateurConcret.

◦ Ainsi, des fonctionnalités supplémentaires peuvent ◦ Ainsi, des fonctionnalités supplémentaires peuvent être ajoutées à la méthode d'origine.

◦ Ces fonctionnalités peuvent être par exemple des traces de log ou une gestion de buffer pour des entrées/sorties.

[email protected]

Page 7: Cours design pattern m youssfi partie 3 decorateur

ImplémentationImplémentation

public interface ComposantAbstrait {

public void operation();

}

public class ComposantConcretImpl1 implements ComposantAbstrait {

@Override

public void operation() {

ComposantAbstrait.java :

ComposantConcretImpl1.java :

[email protected]

public void operation() {

System.out.println("Je sais faire uniquement ça Version 1");

}

}

public class ComposantConcretImpl2 implements ComposantAbstrait {

@Override

public void operation() {

System.out.println("Je sais faire uniquement ça Version 2");

}

}

ComposantConcretImpl2.java :

Page 8: Cours design pattern m youssfi partie 3 decorateur

ImplémentationImplémentation

public abstract class DecorateurAbstrait implements ComposantAbstrait {

protected ComposantAbstrait composantAbstrait;

public DecorateurAbstrait(ComposantAbstrait composantAbstrait) {

super();

this.composantAbstrait = composantAbstrait;

}

}

DecorateurAbstrait.java :

DecorateurConcretImpl1.java :

[email protected]

DecorateurConcretImpl1.java :

public class DecorateurConcretImpl1 extends DecorateurAbstrait {

public DecorateurConcretImpl1(ComposantAbstrait composantAbstrait) {

super(composantAbstrait);

}

@Override

public void operation() {

System.out.println("Décorateur 1 : avant, je je fais X");

composantAbstrait.operation();

System.out.println("Décorateur 1 : après, je je fais Y");

}

}

Page 9: Cours design pattern m youssfi partie 3 decorateur

ImplémentationImplémentationDecorateurConcretImpl2.java :

public class DecorateurConcretImpl2 extends DecorateurAbstrait {

public DecorateurConcretImpl1(ComposantAbstrait composantAbstrait) {

super(composantAbstrait);

}

@Override

public void operation() {

System.out.println("Décorateur 2 : avant, je fais A");

composantAbstrait.operation();

[email protected]

composantAbstrait.operation();

System.out.println("Décorateur 2 : après, je fais B");

}

}

Page 10: Cours design pattern m youssfi partie 3 decorateur

Utilisation du pattern DécorateurUtilisation du pattern DécorateurComposantAbstrait c=new ComposantConcretImpl1();

c.operation();

c :ComposantConcretImpl1

c=new DecorateurConcretImpl1(c);

c.operation();

c :ComposantConcretImpl1:DecorateurConcretImpl1

[email protected]

c :ComposantConcretImpl1:DecorateurConcretImpl1

c=new DecorateurConcretImpl2(c);

c.operation();

c

:ComposantConcretImpl1

:DecorateurConcretImpl2 :DecorateurConcretImpl1

Page 11: Cours design pattern m youssfi partie 3 decorateur

Utilisation du pattern Utilisation du pattern DecorateurDecorateurpublic class Application {

public static void main(String[] args) {

ComposantAbstrait composantAbstrait=new ComposantConcretImpl1();

composantAbstrait.operation();

System.out.println("--------------------"); System.out.println("Première décoration");

System.out.println("--------------------");

composantAbstrait=new DecorateurConcretImpl1(composantAbstrait);

composantAbstrait.operation();

System.out.println("--------------------"); System.out.println("Deuxième décoration");

System.out.println("--------------------");

composantAbstrait=new DecorateurConcretImpl2(composantAbstrait);

composantAbstrait.operation();composantAbstrait.operation();

}}

[email protected]

Je sais faire uniquement ça Version1

--------------------

Première décoration

--------------------

Décorateur 1 : avant, je je fais X

Je sais faire uniquement ça Version1

Décorateur 1 : après, je je fais Y

--------------------

Deuxième décoration

--------------------

Décorateur 2 : avant, je je fais A

Décorateur 1 : avant, je je fais X

Je sais faire uniquement ça Version1

Décorateur 1 : après, je je fais Y

Décorateur 2 : après, je je fais B

Page 12: Cours design pattern m youssfi partie 3 decorateur

ApplicationApplication

[email protected]

Page 13: Cours design pattern m youssfi partie 3 decorateur

Bienvenue chez Bienvenue chez StarbuzzCoffeeStarbuzzCoffee� Starbuzz Coffee s’est fait un nom en devenant la plus

importante chaîne de « salons de café » aux états unis.

� Quand ils ont commencé, ils on conçu leurs classes comme ceci:

BoissonBoisson est une classe abstraite sous-classée par

La variable d’instance description est définie dans chaque sous-classe et contient une description de la

La méthode cout() est abstraite; les sous-classes définir leur propre implémentation

description

getDescription()

cout()

// autres méthodes

Colombia

cout()

Sumatra

cout()

Deca

cout()

Espresso

cout()

abstraite sous-classée par toutes les boissons proposées dans le café

contient une description de la boisson, par exemple « Excellent et corsé »

Chaque sous-classe implémente cout() pur retourner le cout de la boisson

Page 14: Cours design pattern m youssfi partie 3 decorateur

Bienvenue chez Bienvenue chez StarbuzzCoffeeStarbuzzCoffee

� En plus de votre café, vous pouvez également demander plusieurs ingrédients, comme ◦ de la mousse de lait, ◦ du caramel, ◦ du chocolat, ◦ du sirop, ◦ de la vanille ◦ de la vanille ◦ ou noisette ◦ et couronner le tout avec de la crème chantilly.

� Starbuzz Coffee, facturant chacun de ces suppléments, ils ont besoin de les intégrer à leur système de commande

Page 15: Cours design pattern m youssfi partie 3 decorateur

Voici leur premier essaiVoici leur premier essai

Boisson

description

getDescription()

cout()

// autres méthodes

Et bien!

Voila ce que l’on appelle

« une explosion combinatoireune explosion combinatoireune explosion combinatoireune explosion combinatoire »

ColombiaChocolat

cout()

ColombiaLaitChocolatCaramel

cout()

EspressoLaitCaramml

cout()

EspressoLaitChocolat

cout()

Espresso

cout()

SumatraLaitChocolat

cout()

SumatraLaitCaramelChantilly

cout()

SumatraLaitCaramelChantilly

cout()

SumatraLaitCaramelChantilly

cout()

SumatraLaitCaramelChantilly

cout()

SumatraLaitCaramelChantilly

cout()

Espresso

cout()

EspressoChantilly

cout()

Chaque méthode cout() calcule le coût du café plus celui des ingrédients de la commande

Page 16: Cours design pattern m youssfi partie 3 decorateur

Musclez vos neuronesMusclez vos neurones

� De toute évidence, Starbuzz s’est fourré tout seul dans un vrai cauchemar.

� Que va-t-il se passer si le prix du lait change?� Que feront-ils quand il y’a un supplément de vanille?� Au-delà du problème de maintenance, ils enfreignent

l’un des principes de la conception que nous avons déjà vus.l’un des principes de la conception que nous avons déjà vus.◦ Lequel ?

� -

◦ Quelle conception proposez-vous?� -

Page 17: Cours design pattern m youssfi partie 3 decorateur

Une proposition pour éviter l’explosion de Une proposition pour éviter l’explosion de classesclasses

Boisson

description:String

lait:boolean

caramel:boolean

chocolat:boolean

chantilly:boolean

getDescription()getDescription()

cout() // non abstraite

// autres méthodes

Colombia

cout()

Sumatra

cout()

Deca

cout()

Espresso

cout()

Page 18: Cours design pattern m youssfi partie 3 decorateur

Ecrivez les méthodes cout() pour les deux classes Ecrivez les méthodes cout() pour les deux classes suivantes: (pseudo code uniquement)suivantes: (pseudo code uniquement)

/*Boisson.java*/

public class Boisson {

protected String description;

protected boolean lait;

protected boolean caramel;

protected boolean chocolat;

protected boolean chantilly;

/*Espresso.java*/

public class Espresso extends

Boisson {

public Espresso() {

description="Espresso";

}

@Override

public double cout() {

return super.cout()+6;public double cout(){

double prixIngerdients=0;

if(lait==true) prixIngerdients+=2;

if(caramel==true) prixIngerdients+=1;

if(chocolat==true) prixIngerdients+=1.5;

if(chantilly==true) prixIngerdients+=0.5;

return prixIngerdients;

}

// Getters et Setters

}

return super.cout()+6;

}

}

/*Application.java*/

Espresso boisson=new Espresso();

System.out.println(boisson.cout());

boisson.setCaramel(true);

boisson.setChantilly(true);

System.out.println(boisson.cout());

Page 19: Cours design pattern m youssfi partie 3 decorateur

A vos crayons!A vos crayons!

� Quelles sont les exigences et les autres facteurs qui pourraient changer et avoir un impact négatif sur cette conception?

◦ Application ouverte à la modification pour chaque ajout de nouveau ingrédients

◦ Attribuer des fonctionnalités non appropriées aux classes dérivées◦ Attribuer des fonctionnalités non appropriées aux classes dérivées

◦ Impossibilité de multiplier l’application des ingrédients

◦ -

◦ -

◦ -

◦ -

◦ -

◦ -

Page 20: Cours design pattern m youssfi partie 3 decorateur

Principe Ouvert Principe Ouvert -- FerméFerméPrincipe de conception:

Les classes doivent être ouvertes à l’extension et fermées à la modification

5ème Principe de conception

� Notre but est de permettre d’étendre facilement les classes pour incorporer de nouveaux comportements sans modifier le code existant.

� Qu’obtiendrons-nous, si nous y parvenons?

◦ Des conceptions résistantes au changement et suffisamment souples pour accepter de nouvelles fonctionnalités répondant à l’évolution des besoins.

5ème Principe de conception

Page 21: Cours design pattern m youssfi partie 3 decorateur

Faites connaissance du «Faites connaissance du « Pattern DécorateurPattern Décorateur »»

� Nous avons vu que représenter notre boisson plus le schéma de tarification des ingrédients au moyen de l’héritage n’a pas bien fonctionné; nous obtenons ◦ une explosion de classes,

◦ une conception rigide,

◦ ou nous ajoutons à la classe de base des fonctionnalités non appropriée pour certaines sous-classes.

� Voici ce que nous allons faire. � Voici ce que nous allons faire. ◦ Nous allons commencer par une boisson

◦ et nous allons la décorer avec des ingrédients au moment de l’exécution.

� Si, par exemple, le client veut un Sumatra avec Chocolat et Chantilly, nous allons:◦ Créer un objet Sumatra

◦ Le décorer avec un objet Chocolat

◦ Le décorer avec un objet Chantilly

◦ Appeler la méthode cout() et nous appuyer sur la délégation pour ajouter les coûts des ingrédients.

Page 22: Cours design pattern m youssfi partie 3 decorateur

Construire une boisson avec des décorateursConstruire une boisson avec des décorateurs

� Commençons par créer un objet Sumatra

◦ Boisson b1=new Sumatra();

:Sumatra

cout()

� Le client veut ajouter du chocolat. Nous créer donc un objet Chocolat et nous enveloppons le Sumatra dedans.

b1

enveloppons le Sumatra dedans.

� b1=new Chocolat(b1);

� Le Client veut aussi du Chantilly. Nous créons un décorateur Chantilly et nous enveloppons Chocolat dedans.

� B1=new Chantilly(b1);

:Chocolat

cout()b1

:Sumatra

cout()

:Chantilly

cout()b1

:Chocolat

cout()

:Sumatra

cout()

Page 23: Cours design pattern m youssfi partie 3 decorateur

Application du pattern Décorateur à notre problèmeApplication du pattern Décorateur à notre problème

Boisson

description

getDescription()

cout()

//Autres méthodes

DecorateurIngredient

1 composantBoisson joue le rôle de notre

classe abstraite

Colombia

cout()

DecorateurIngredient

getDescription()

Les quatre composants concrets :

un par type de café

Sumatra

cout()Deca

cout()

Espresso

cout()

Lait

boisson:Boisson

cout()

getDescription()

Chocolat

boisson:Boisson

cout()

getDescription()

Caramel

boisson:Boisson

cout()

getDescription()

Chantilly

boisson:Boisson

cout()

getDescription()

Et voici nos décorateurs pour les ingrédients remarquez qu’ils implémentent cout() et getDescription()

Page 24: Cours design pattern m youssfi partie 3 decorateur

Implémentation de Implémentation de StarbuzzStarbuzz

public abstract class Boisson {

String description;

public String getDescription() {

return description;

}

public abstract double cout();

Boisson.java

public abstract double cout();

}

public abstract class DecorateurIngredient extends Boisson {

protected Boisson boisson;

public DecorateurIngredient(Boisson boisson) {

this.boisson = boisson;

}

public abstract String getDescription();

}

DecorateurIngredient.java

Page 25: Cours design pattern m youssfi partie 3 decorateur

Coder les boissonsCoder les boissons

public class Espresso extends Boisson {

public Espresso(){

description="Espresso";

}

public double cout() {

return 1.99;

}

Espresso.java

}

}

public class Colombia extends Boisson {

public Colombia(){

description="Colombia";

}

public double cout() {

return .89;

}

}

Columbia.java

Page 26: Cours design pattern m youssfi partie 3 decorateur

Coder les ingrédients (Décorateurs)Coder les ingrédients (Décorateurs)

public class Chocolat extends DecorateurIngredient {

public Chocolat(Boisson boisson) { super(boisson); }

public double cout() { return 0.20 +boisson.cout() ;

}

public String getDescription() {

return boisson.getDescription()+", Chocolat";

}

}

Chocolat.java

public class Caramel extends DecorateurIngredient {

public Caramel(Boisson boisson) { super(boisson); }

public double cout() { return 0.22 +boisson.cout() ; }

public String getDescription() {

return boisson.getDescription()+", Caramel";

}

}

Caramel.java

Page 27: Cours design pattern m youssfi partie 3 decorateur

Le café est serviLe café est servi

public class ApplicationDecorateur {

public static void main(String[] args) {

Boisson b1=new Espresso();

System.out.println(b1.getDescription()+" € "+b1.cout());

Boisson b2=new Colombia();

b2=new Caramel(b2);b2=new Caramel(b2);

b2=new Chocolat(b2);

b2=new Chocolat(b2);

System.out.println(b2.getDescription()+" € "+b2.cout());

}

}

Page 28: Cours design pattern m youssfi partie 3 decorateur

A vos crayons : Dessinez vos objetsA vos crayons : Dessinez vos objets

Page 29: Cours design pattern m youssfi partie 3 decorateur

ExerciceExercice� InputStream du package ja.io est une classe abstraite dont plusieurs

implémentations concrètes définissent une méthode read() qui permet de lire un entier à partir d’une entrée quelconque.

� La classe Concrète FileInpustream est un InputStream qui permet de lire des entiers à partir d’un fichier :◦ Pour créer l’objet:

� InputStream is=new FileInputStream("original.txt");

◦ Pour lire un entier du fichier:� int c=is.read();

� Nous souhaitons créer un décorateur de InputStream qui nous permet de décrypter un fichier qui contient une suite de nombres paires. Le décryptage consiste à récupérer du fichiers deux nombre par deux nombres en faisant décrypter un fichier qui contient une suite de nombres paires. Le décryptage consiste à récupérer du fichiers deux nombre par deux nombres en faisant la différence entre les deux.◦ Exemple : Si le fichier contient le texte : bacadb

◦ Le nombre décrypté est obtenu comme suit:� code ascii (b)-code ascii(a) = 1 � code ascii (c)-code ascii(a) = 2 � code ascii (d)-code ascii(b) = 2

◦ Le nombre décrypté est 122.

◦ Pour créer l’objet DecrypteInputStream, on peut écrire� is=new DecrypteurInputStream(is);

◦ Pour lire un nombre décrypté� int c=is.read();

Page 30: Cours design pattern m youssfi partie 3 decorateur

Travail à faireTravail à faire� Créer un diagramme de classes

� Créer un décorateur abstrait de InpuStream : DecorateurInputStream.java

� Créer un Décorateur concret de InputStream, qui permet de décrypter un InputStream : DecrypteInputStream.java

� Créer un fichier texte « original.txt » qui contient le texte crypté

Créer une application qui permet de:� Créer une application qui permet de:

◦ Créer un FileInputStream représentant le fichier « Original.txt »

◦ Décorer l’objet créé par un objet de DecrypteInputStream

◦ Afficher le texte décrypté