0% ont trouvé ce document utile (0 vote)
180 vues75 pages

Principes et patrons de conception OO

Transféré par

rahma kalboussi
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)
180 vues75 pages

Principes et patrons de conception OO

Transféré par

rahma kalboussi
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

Méthodologie de Développement Objet

Partie 2 : Principes et patrons de conception orientée objet

Christine Solnon

INSA de Lyon - 4IF

2019 - 2020

1/57 .
Plan du cours

1 Introduction

2 Illustration de design patterns avec PlaCo

3 Encore quelques patrons du GoF

2/57 .
Quelques principes de conception orientée objet

Protection des variations : Identifier les points de variation et d’évolution,


et séparer ces aspects de ceux qui demeurent constants
Faible couplage : Réduire l’impact des modifications en minimisant les
dépendances entre classes
Forte cohésion : Faciliter la compréhension, gestion et réutilisation des
objets en concevant des classes à but unique
Indirection : Limiter le couplage et protéger des variations en ajoutant des
objets intermédiaires
Programmer pour des interfaces : Limiter le couplage et protéger des
variations en faisant abstraction de l’implémentation
Composer au lieu d’hériter : Utiliser la composition au lieu de l’héritage
pour déléguer une tâche à un objet, changer dynamiquement
le comportement d’une instance, ...

Ces principes se retrouvent dans beaucoup de Design Patterns...

3/57 .
Patrons de conception (Design patterns)

Qu’est-ce qu’un patron de conception ?


Solution générale et réutilisable d’un problème récurrent
; Formalisation de bonnes pratiques

Comment décrire un patron de conception


Nom ; Vocabulaire de conception
Problème : Description du sujet à traiter et de son contexte
Solution : Description des éléments, de leurs relations/coopérations et
de leurs rôles dans la résolution du problème
Description générique
Illustration sur un exemple
Conséquences : Effets résultant de la mise en œuvre du patron
; Complexité en temps/mémoire, impact sur la flexibilité, portabilité, ...

4/57 .
23 patrons du Gang of Four (GoF)
[E. Gamma, R. Helm, R. Johnson, J. Vlissides]

Patrons illustrés avec PlaCo :


Création : Factory, Singleton
Comportement : Iterateur, Etat, Observateur, Commande, Visiteur
Structure : PoidsPlume

Patrons introduits en fin de cours :


Création : Abstract factory
Comportement : Stratégie
Structure : Décorateur, Adaptateur, Facade, Composite

Patron introduit pour le projet :


Comportement : Template

Patrons qui ne seront pas vus dans ce cours :


Création : Prototype, Builder
Comportement : Chaine de resp., Interpreteur, Mediateur, Memento
Structure : Pont, Proxy
5/57 .
Plan du cours

1 Introduction

2 Illustration de design patterns avec PlaCo

3 Encore quelques patrons du GoF

6/57 .
L’application PlaCo (rappel)
Une scierie, équipée d’une machine de découpe au laser, veut un système
pour dessiner les plans à transmettre à la machine.
L’application doit permettre d’ajouter, supprimer et déplacer des formes
sur un plan, de sauvegarder et charger des plans, et de transmettre un
plan au système de découpe.
Chaque plan a une hauteur et une largeur.
Les formes sur un plan sont des rectangles et des cercles :
un rectangle a une largeur et une hauteur, et sa position est définie
par les coordonnées de son coin supérieur gauche ;
un cercle a un rayon, et sa position est définie par les coordonnées
de son centre.
Les coordonnées et les longueurs sont des valeurs entières exprimées
dans une unité donnée. Les formes doivent avoir des intersections vides.

Pour télécharger le code Java de PlaCo :


[Link]/csolnon/[Link]
7/57 .
Diagramme de cas d’utilisation de PlaCo (rappel)

8/57 .
Polymorphisme

Problème :
Si les affaires marchent bien, la scierie envisage d’étendre le système pour
découper des triangles, des ellipses, ...

Solution : Utiliser le polymorphisme pour se protéger des variations


Créer une interface Forme déclarant les méthodes communes à toutes
les formes
Créer deux classes Cercle et Rectangle réalisant Forme
Utiliser le polymorphisme pour traiter de façon uniforme les instances de
Cercle et Rectangle

Principes mis en œuvre :


Programmer pour des interfaces
Protection des variations

9/57 .
10/57 .
Pattern GoF : Itérateur (1/3)

Problème :
L’équipe de développement hésite sur le choix de la structure de données à
utiliser pour mémoriser les formes du plan

Solution : Utiliser le pattern Itérateur


Permet de parcourir la collection de formes sans connaître la structure de
données utilisée

Principes mis en œuvre :


Programmer pour des interfaces
Protection des variations
Forte cohésion

11/57 .
Pattern GoF : Itérateur (2/3)

Que faut-il changer si on veut utiliser Vector au lieu de ArrayList ?


Pourquoi séparer Iterator de Collection ?

12/57 .
Pattern GoF : Itérateur (3/3)

Séparer Iterator de Collection permet d’avoir plusieurs itérateurs


sur une même collection en même temps :

13/57 .
Architecture Modèle-Vue-Contrôleur (MVC)

Problèmes :
L’utilisateur peut demander de changer la façon d’interagir avec PlaCo :
Ajouter un menu avec liste déroulante pour sélectionner une forme
à ajouter
Ajouter une description textuelle du plan, en plus de la visualisation
graphique
Changer la façon de saisir les informations pour ajouter une
nouvelle forme dans le plan
etc
La technologie utilisée pour la visualisation peut changer
La classe Plan perd en cohésion si elle doit s’occuper d’afficher le plan

Solution :
Architecture MVC !

14/57 .
Architecture Modèle-Vue-Contrôleur (MVC)
Modèle : Met à jour et traite les données "métier"
Ajoute/supprime/déplace des formes sur un plan
; Détermine si deux formes ont une intersection vide

Vue : Visualise le modèle et interagit avec l’utilisateur


Dessine le plan à l’écran, affiche la liste des formes, etc
Détecte les clics de souris, frappe de caractères, etc

Contrôleur : Traduit les interactions entre l’utilisateur et la vue en


actions pour le modèle ou la vue
Demande au modèle de déplacer une forme quand l’utilisateur a frappé
sur une flêche après avoir sélectionné une forme
Demande au modèle d’ajouter un rectangle au plan quand l’utilisateur a
cliqué sur un point après avoir cliqué sur le bouton "Ajouter un rectangle"
etc
15/57 .
Architecture Modèle-Vue-Contrôleur (MVC)

Flêche pleine = dépendance


Pointillés = événements

Principes mis en œuvre :


Protection des variations
Forte cohésion

Problème : Comment indiquer à Vue les modifications de Modèle ?


Solution 1 : Modèle envoie un message à Vue quand il est modifié
Inconvénient : Modèle devient dépendant de Vue ⇒ Interdit !
Solution 2 : Contrôleur envoie un message à Vue qd Modèle est modifié
Solution 3 : Utiliser le pattern Observateur
16/57 .
Pattern GoF : Observateur (aka Publish/Subscribe) (1/2)

17/57 .
Pattern GoF : Observateur (aka Publish/Subscribe) (1/2)

17/57 .
Pattern GoF : Observateur (aka Publish/Subscribe) (1/2)

17/57 .
Pattern GoF : Observateur (aka Publish/Subscribe) (1/2)

17/57 .
Pattern GoF : Observateur (aka Publish/Subscribe) (2/2)

Solution générique [Wikipedia] :

Principes mis en œuvre :


Faible couplage entre ConcreteObserver et Subject
Protection des variations : Ajout d’observateurs sans modifier Subject

Remarque :
Les données de Subject peuvent être “poussées” (dans notify) ou
“tirées” (avec des getters)
18/57 .
Observer et Observable “deprecated” dans Java 9

Pourquoi ?
notifyObservers ne spécifie pas l’ordre de notification
update ne connait pas la classe de l’objet Observable
Un objet Observable ne peut pas être sérialisé

Mais cela ne veut pas dire que le design pattern n’est pas bon !
On le retrouve dans les “Listeners”
Il peut être facilement implémenté (sans utiliser
[Link])
On peut utiliser PropertyChangeEvent et
PropertyChangeListener de [Link]

19/57 .
Pattern GoF : Visiteur (1/3)
Problème :
Perte de la classe effective des formes dans VueGraphique

Solution 1 : Tester la classe des instances avant de les afficher

Inconvénients :
Peut devenir lourd si
Forme a beaucoup de
sous-classes
Même problème pour
VueTextuelle

Solution 2 : Utiliser le pattern Visiteur

20/57 .
Pattern GoF : Visiteur (2/3)

21/57 .
Pattern GoF : Visiteur (2/3)

21/57 .
Pattern GoF : Visiteur (2/3)

21/57 .
Pattern GoF : Visiteur (3/3)

Solution générique [Wikipedia] :


Principes mis en œuvre :
Forte cohésion : Permet de
regrouper dans chaque
réalisation de Visitor toutes
les methodes liées à un
aspect (visualisation,
persistence, ...) de toutes les
sous-classes de Element
Protection des variations :
Ajout de nouvelles
réalisations de Visitor sans
modifier ConcreteElement

22/57 .
Architecture actuelle de PlaCo

Comment l’utilisateur interagit-il avec PlaCo ?

23/57 .
Architecture actuelle de PlaCo

Comment l’utilisateur interagit-il avec PlaCo ?


Fenêtre utilise des écouteurs d’événements (Listeners)
Les écouteurs transmettent les événements à Contrôleur

23/57 .
Comment déterminer les événements à écouter ?

En examinant les cas


d’utilisation :
Chaque cas d’utilisation est
activé par un événement (clic
sur bouton, sélection menu,
etc)
Les scénarios permettent de
lister les autres événements
possibles

24/57 .
Extraction des événements à partir des scénarios

Exemple : Scénario principal de "Ajouter un rectangle"


1 L’utilisateur indique au système qu’il veut ajouter un rectangle
2 Le système demande de saisir les coordonnées d’un angle du rectangle
3 L’utilisateur saisit les coordonnées d’un point p1
4 Le système demande de saisir les coordonnées de l’angle opposé
5 L’utilisateur saisit les coordonnées d’un point p2
6 Le système ajoute le rectangle correspondant dans le plan
7 Le système affiche le plan avec le rectangle ajouté
Alternative [1-5a] : L’utilisateur indique qu’il souhaite annuler la saisie

Evénements utilisateurs :
Clic sur le bouton "Ajouter un rectangle"
Clic gauche de la souris sur la vue graphique du plan
Clic droit de la souris ou [Esc]

25/57 .
Extraction des événements à partir des scénarios

Exemple : Scénario principal de "Ajouter un rectangle"


1 L’utilisateur indique au système qu’il veut ajouter un rectangle
2 Le système demande de saisir les coordonnées d’un angle du rectangle
3 L’utilisateur saisit les coordonnées d’un point p1
4 Le système demande de saisir les coordonnées de l’angle opposé
5 L’utilisateur saisit les coordonnées d’un point p2
6 Le système ajoute le rectangle correspondant dans le plan
7 Le système affiche le plan avec le rectangle ajouté
Alternative [1-5a] : L’utilisateur indique qu’il souhaite annuler la saisie

Evénements utilisateurs :
Clic sur le bouton "Ajouter un rectangle"
Clic gauche de la souris sur la vue graphique du plan
Clic droit de la souris ou [Esc]

25/57 .
Extraction des événements à partir des scénarios

Exemple : Scénario principal de "Ajouter un rectangle"


1 L’utilisateur indique au système qu’il veut ajouter un rectangle
2 Le système demande de saisir les coordonnées d’un angle du rectangle
3 L’utilisateur saisit les coordonnées d’un point p1
4 Le système demande de saisir les coordonnées de l’angle opposé
5 L’utilisateur saisit les coordonnées d’un point p2
6 Le système ajoute le rectangle correspondant dans le plan
7 Le système affiche le plan avec le rectangle ajouté
Alternative [1-5a] : L’utilisateur indique qu’il souhaite annuler la saisie

Evénements utilisateurs :
Clic sur le bouton "Ajouter un rectangle"
Clic gauche de la souris sur la vue graphique du plan
Clic droit de la souris ou [Esc]

25/57 .
Extraction des événements à partir des scénarios

Exemple : Scénario principal de "Ajouter un rectangle"


1 L’utilisateur indique au système qu’il veut ajouter un rectangle
2 Le système demande de saisir les coordonnées d’un angle du rectangle
3 L’utilisateur saisit les coordonnées d’un point p1
4 Le système demande de saisir les coordonnées de l’angle opposé
5 L’utilisateur saisit les coordonnées d’un point p2
6 Le système ajoute le rectangle correspondant dans le plan
7 Le système affiche le plan avec le rectangle ajouté
Alternative [1-5a] : L’utilisateur indique qu’il souhaite annuler la saisie

Evénements utilisateurs :
Clic sur le bouton "Ajouter un rectangle"
Clic gauche de la souris sur la vue graphique du plan
Clic droit de la souris ou [Esc]

25/57 .
Liste des événements utilisateur de PlaCo :
Clic sur un bouton : AjouterCercle, AjouterRectangle, . . . , Undo, Redo
Frappe d’une touche au clavier : flêches, [Ctr Z], [Shift Ctr Z], [Esc]
Clic gauche de la souris sur la vue graphique
Clic droit de la souris sur la vue graphique
Déplacement de la souris sur la vue graphique

Remarque : Cette IHM est très probablement critiquable


Nous voyons ici comment concevoir PlaCo pour pouvoir facilement changer l’IHM !
26/57 .
Liste des événements utilisateur de PlaCo :
Clic sur un bouton : AjouterCercle, AjouterRectangle, . . . , Undo, Redo
Frappe d’une touche au clavier : flêches, [Ctr Z], [Shift Ctr Z], [Esc]
Clic gauche de la souris sur la vue graphique
Clic droit de la souris sur la vue graphique
Déplacement de la souris sur la vue graphique

Remarque : Cette IHM est très probablement critiquable


Nous voyons ici comment concevoir PlaCo pour pouvoir facilement changer l’IHM !
26/57 .
Que font les écouteurs ?

Ils délèguent à Controleur !

27/57 .
Que fait Contrôleur ?

Contrôleur a une méthode pour chaque événement utilisateur :

Que font les méthodes de Contrôleur ?


Ca dépend du cas d’utilisation
; Dessiner un diagramme Etats-Transitions

28/57 .
Diagramme Etats-Transitions de PlaCo

29/57 .
Diagramme Etats-Transitions de PlaCo

Que fait la méthode clicGauche(p) de Controleur ?


29/57 .
Pattern GoF : Etat (State) (1/5)
Problème :
Ce que doit faire Contrôleur à la réception du message clicGauche(p)
dépend de son état courant

Solution 1 :
Contrôleur a un attribut
etatCourant mémorisant son état
clicGauche(p) contient un cas par
état possible

Avantages et inconvénients ?

Solution 2 : Utiliser le pattern Etat


Encapsuler les états dans des classes implémentant une même interface
30/57 .
Pattern GoF : Etat (State) (2/5)

Controleur délègue à etatCourant :


public void ajouterCercle(){ ajouterCercle(this,fenetre) ; }
public void ajouterRectangle(){ ajouterRectangle(this,fenetre) ; }
public void supprimer(){ [Link](this,fenetre) ; }
... etc ...
31/57 .
Pattern GoF : Etat (State) (3/5)
Comment Controleur change-t-il d’état ?
Méthode setEtatCourant(Etat e) de Controleur

Comment récupérer les instances d’Etat ?


Solution 1 : Créer une nouvelle instance à chaque changement d’état
Solution 2 : Les classes Etat sont des singletons (cf fin du cours)
Solution 3 : Contrôleur possède une instance de chaque classe Etat

32/57 .
Pattern GoF : Etat (State) (4/5)
Code de la méthode clicGauche :
Dans la classe Contrôleur

Dans l’interface Etat (utilisation de “default” introduit dans Java 8))

Dans la classe EtatCercle1

Dans la classe EtatCercle2

etc.
33/57 .
Pattern GoF : State (5/5)

Solution générique :
[Wikipedia]

Principes mis en œuvre :


Forte cohésion : Chaque ConcreteState contient les méthodes des
événements qui ont un effet sur lui
Protection des variations : Ajout d’un nouvel état facile (mais ajout d’un
nouvel événement plus fastidieux)
Programmer pour des interfaces

34/57 .
Architecture actuelle de PlaCo)

Problème : Comment mettre en œuvre les undo/redo ?


35/57 .
Pattern GoF : Commande (1/2)

Cde Ajout :

36/57 .
Pattern GoF : Commande (1/2)

Ajout d’un nouveau cercle en entrant dans EtatCercle2 :

36/57 .
Pattern GoF : Commande (1/2)

Undo/Redo :

36/57 .
Pattern GoF : Commande (2/2)
Solution générique :
Client crée les instances
de ConcreteCommand
Invoker demande
l’exécution des commandes
ConcreteCommande
délègue l’exécution à
Receiver

Remarques :
Découple la réception d’une requête de son exécution
Les rôles de Client et Invoker peuvent être joués par une même
classe (par exemple le contrôleur)
Permet la journalisation des requêtes pour reprise sur incident
Permet d’annuler ou ré-exécuter des requêtes (undo/redo)
37/57 .
Diagrammes de séquence (1/2)

Vérification de la cohérence avec le diagramme de classes :


EcouteurDeBoutons doit avoir une visibilité sur controleur
; EcouteurDeBoutons a un attribut controleur
Controleur doit avoir une méthode clicGauche(p)
Controleur doit avoir une visibilité sur etatCourant
; Controleur a un attribut etatCourant
Etat doit avoir une méthode clicGauche(fenetre,plan,cdes,p)

Remarque :
clicGauche(fenetre,plan,cdes,p) est un message polymorphe
; Faire un diagramme de séquence pour chaque classe réalisant Etat
38/57 .
Diagrammes de séquence (2/2)

39/57 .
Patterns GoF : Poids Plume (FlyWeight) et Factory
Problème :
Nombreuses créations/destructions d’instances de Point

Solution :
Partager la même instance pour les points de mêmes coordonnées
; Attention : changer d’instance pour déplacer un point !
Utiliser une Factory pour créer/mémoriser les instances

40/57 .
Patterns GoF : Poids Plume (FlyWeight) et Factory
Problème :
Nombreuses créations/destructions d’instances de Point

Solution :
Partager la même instance pour les points de mêmes coordonnées
; Attention : changer d’instance pour déplacer un point !
Utiliser une Factory pour créer/mémoriser les instances

40/57 .
Patterns GoF : Poids Plume (FlyWeight) et Factory
Problème :
Nombreuses créations/destructions d’instances de Point

Solution :
Partager la même instance pour les points de mêmes coordonnées
; Attention : changer d’instance pour déplacer un point !
Utiliser une Factory pour créer/mémoriser les instances

40/57 .
Architecture actuelle de PlaCo

Il manque encore une chose ?


41/57 .
Architecture actuelle de PlaCo

Il manque encore une chose ?


; Charger/sauver un plan à partir d’un fichier XML 41/57 .
Diagramme de classes du package xml

Problème : Comment accéder à [Link]()


depuis n’importe quelle classe du package ?
Rendre ouvre() statique ?
Impossible si OuvreurDeFichierXML est son propre FileFilter

Utiliser un Singleton
42/57 .
Patron GoF : Singleton

OuvreurDeFichierXML ne peut avoir qu’une seule instance et cette


instance est accessible à toutes les classes du package
; [Link]()

Attention :
Parfois considéré comme un anti-pattern... à utiliser avec modération !

43/57 .
Plan du cours

1 Introduction

2 Illustration de design patterns avec PlaCo

3 Encore quelques patrons du GoF

44/57 .
23 patrons du Gang of Four (GoF)
[E. Gamma, R. Helm, R. Johnson, J. Vlissides]

Patrons qu’on vient d’illustrer avec PlaCo :


Création : Factory, Singleton
Comportement : Iterateur, Etat, Observateur, Commande, Visiteur
Structure : PoidsPlume

Patrons qu’on va voir maintenant :


Création : Abstract factory
Comportement : Stratégie
Structure : Décorateur, Adaptateur, Facade, Composite

Patron introduit pour le projet :


Comportement : Template

Patrons qui ne seront pas vus dans ce cours :


Création : Prototype, Builder
Comportement : Chaine de resp., Interpreteur, Mediateur, Memento
Structure : Pont, Proxy
45/57 .
Patron GoF : Abstract factory (1/2)
Problème :
Créer une famille d’objets sans spécifier leurs classes concrêtes

Illustration sur un exemple :


Créer une interface graphique avec widgets (boutons, menus, ...)
Point de variation : OS (Linux, OSX, Windows)

1 ...
AbstractGUIfactory Client AbstractGUIfactory f;
+créeBouton(...) if (..) f=new GUIfactoryOSX();
+créeMenu(...) else f=new GUIfactoryLinux();
...
Bouton b=[Link]éeBouton(...);
Menu m=[Link]éeMenu(...);
...

GUIfactoryOSX GUIfactoryLinux
public Bouton créeBouton(...){
+créeBouton(...) +créeBouton(...) return new BoutonLinux(...);
+créeMenu(...) +créeMenu(...) }

Bouton * * Menu
+dessine(...) +actionMenu(...)

BoutonLinux BoutonOSX MenuLinux MenuOSX


+dessine(...) +dessine(...) +actionMenu(...) +actionMenu(...)

46/57 .
Patron GoF : Abstract factory (2/2)

Remarques :
Solution Générique [Wikipedia] :
AbstractFactory et AbstractProduct
sont généralement des interfaces
; Programmer pour des interfaces
Les méthodes createProduct. . . ()
sont des factory methods

Avantages du pattern :
Indirection : Isole Client des
implémentations des produits
Protection des variations : Facilite la
substitution de familles de produits
Maintien automatique de la
cohérence

Mais l’ajout de nouveaux types de


produits est difficile...

47/57 .
Patron GoF : Strategy (1/3)

Problème :
Changer dynamiquement le comportement d’un objet

Illustration sur un exemple :


Dans un jeu vidéo, des personnages combattent des monstres...
; méthode combat(Monstre m) de la classe Perso
...et le code de combat peut être différent d’un personnage à l’autre
Sol. 1 : combat contient un cas pour chaque type de combat
Sol. 2 : La classe Perso est spécialisée en sous-classes qui
redéfinissent combat

Représenter ces solutions en UML. Peut-on facilement :


Ajouter un nouveau type de combat ?
Changer le type de combat d’un personnage ?

48/57 .
Patron GoF : Strategy (1/3)

Problème :
Changer dynamiquement le comportement d’un objet

Illustration sur un exemple :


Dans un jeu vidéo, des personnages combattent des monstres...
; méthode combat(Monstre m) de la classe Perso
...et le code de combat peut être différent d’un personnage à l’autre
Sol. 1 : combat contient un cas pour chaque type de combat
Sol. 2 : La classe Perso est spécialisée en sous-classes qui
redéfinissent combat
Sol. 3 : La classe Perso délègue le combat à des classes
encapsulant des codes de combat et réalisant toutes une même
interface
Représenter ces solutions en UML. Peut-on facilement :
Ajouter un nouveau type de combat ?
Changer le type de combat d’un personnage ?

48/57 .
Patron GoF : Strategy (2/3)
Diagramme de classes de la solution 3 :

Code Java de la classe Perso :

Comment créer l’instance


de TypeCombat correspondant
à niveau ?

49/57 .
Patron GoF : Strategy (2/3)
Diagramme de classes de la solution 3 :

Code Java de la classe Perso :

49/57 .
Patron GoF : Strategy (3/3)
Solution générique :
[Wikipedia]

Remarques :
Principes de conception orientée objet mobilisés :
Indirection : Isole Context des implémentations de Strategy
; Protection des variations
Composer au lieu d’hériter : Changer dynamiquement de stratégie
Passage d’informations de Context à Strategy
en “poussant” : l’info est un param de AlgorithmInterface()
en “tirant” : le contexte est un param. de AlgorithmInterface()
qui utilise des getters pour récupérer l’info
50/57 .
Patron GoF : Adaptateur
Problème :
Fournir une interface stable (Adaptateur) à un composant dont l’interface
peut varier (Adapté)

Solution générique :

; Application des principes “indirection” et “protection des variations”

Exercices :
Dessiner le diagramme de séquence de l’envoi du message
opClient() à une instance de Client
Comment faire s’il y a plusieurs composants (Adapté) différents, et que
l’on veut pouvoir choisir dynamiquement la classe adaptée ?
51/57 .
Patron GoF : Facade
Problème :
Fournir une interface simplifiée (Facade)

Solution générique [Wikipedia] :

; Application des principes “indirection” et “protection des variations”


52/57 .
Patron GoF : Décorateur (1/2)
Problème :
Attacher dynamiquement des responsabilités supplémentaires à un objet

Illustration sur un exemple :


Exemple d’utilisation :
...
Pizza p=new PizzaClassique();
p = new Fromage(p);
p = new Jambon(p);
Pizza ...
1
calcPrix() #pizza
affDescr()
public DécorateurPizza(Pizza p){
[Link] = p;
}
PizzaPateFine PizzaClassique DécorateurPizza
@override
calcPrix() calcPrix() calcPrix() public double calcPrix(){
affDescr() affDescr() affDescr() return [Link]();
}

@override
Fromage Oignon Jambon public Jambon(Pizza p){
public double calcPrix(){ super(p);
return prixFromage calcPrix() calcPrix() calcPrix() }
+ [Link](); affDescr() affDescr() affDescr()
}

53/57 .
Patron GoF : Décorateur (2/2)

Solution générique : Remarques :


Composer au lieu d’hériter : Ajout
dynamique de responsabilités à
ConcreteComponent sans le
modifier
n décors ⇒ 2n combinaisons
Inconvénient : Peut générer de
nombreux petits objets “enveloppes”

[Wikipedia]

Utilisation pour décorer les classes d’entrée/sortie en Java :


Component : InputStream, OutputStream
ConcreteComponent : FileInputStream, ByteArrayInputStream, ...
Decorator : FilterInputStream, FilterOutputStream
ConcreteDecorator : BufferedInputStream, CheckedInputStream, ...

54/57 .
Adaptateur, Facade et Décorateur

Points communs :
Indirection ; Enveloppe (wrapper)
Protection des variations

Différences :
Adaptateur : Convertit une interface en une autre (attendue par un
Client)
Facade : Fournit une interface simplifiée
Décorateur : Ajoute dynamiquement des responsabilités aux méthodes
d’une interface sans la modifier

55/57 .
Patron GoF : Composite (1/2)
Problème :
Représenter des hiérarchies composant/composé et traiter de façon uniforme
les composants et les composés

Illustration sur un exemple : :EltCompXML


tag="livres"

< ?xml version="1.0" ?>


<livres>
<livre> :EltCompXML :EltCompXML
<titre>Guerre et paix</titre> tag="livre" tag="livre"
<auteur>Tolstoï</auteur>
<nbPages>1572</nbPages>
</livre>
<livre> :EltSimpleXML :EltSimpleXML :EltCompXML
<titre>20 ans après</titre> tag="titre" tag="titre" tag="publication"
<auteur>Dumas</auteur> val="Guerre et paix" val="20 ans après"
<publication>
<ed>Lebègue</ed> :EltSimpleXML :EltSimpleXML
<date>1848</date> tag="auteur" tag="auteur" :EltSimpleXML
</publication> val="Tolstoi" val="Dumas" tag="date"
</livre> val="1848"
</livres> :EltSimpleXML
tag="nbPages" :EltSimpleXML
val="1572" tag="ed"
Comment compter le val="Lebègue"

nombre de tags ?
56/57 .
Patron GoF : Composite (2/2)
Solution générique : *
Composant fils
attCommun
opCommune()

Feuille Composite
attCommun attCommun
... ...
opCommune() opCommune()
... ...

Exercices :
Définir les opérations permettant de :
Compter le nombre de fils d’un composant
Compter le nombre de descendants d’un composant
Ajouter un fils à un composant
Comment accéder séquentiellement aux fils d’un Composite ?
Comment accéder séquentiellement aux descendants d’un Composite ?
57/57 .

Vous aimerez peut-être aussi