Vous êtes sur la page 1sur 78

10/11/2020

DESIGN PATTERNS
PatronS de conception

Pr. ZAKRANI Abdelali


ENSAM - CASABLANCA
Zakrani.ensam@gmail.com

2020-2021 Design Patterns 2

Plan
Introduction
Rappel sur la programmation objet
Principes de conception SOLID
Patrons de conception
Patrons de création: Fabrique, Fabrique abstraite, Prototype,
Singleton, Monteur
Patrons de structure: Décorateur, Adapteur, Façade, Pont, Objet
composite, Poids-mouche, Proxy
Patrons de comportement: Observateur, Stratégie, Commande,
Médiateur, Chaîne de responsabilité, Itérateur, Interpréteur, Etat,
Patron de méthode, Visiteur, Fonction de rappel

1
10/11/2020

2020-2021 Design Patterns 3

Rappel sur l’approche Objet


Concepts de base
Classes/objets
Les classes sont des modèles pour créer des objets qui
communiquent entre eux par messages (appels de méthodes)
Encapsulation
On cache (private) la structure d'un objet et on ne révèle (public) que
les fonctions (méthodes) nécessaires
Héritage
Une classe peut hériter des données et des méthodes d'autres
classes
Polymorphisme (d'héritage)
Une méthode de même signature peut avoir des comportements
(instructions) différents selon la classe ou elle est (re)définie.

2020-2021 Design Patterns 4

Intérêts des concepts objets de base


Sécurité
L'encapsulation permet de protéger un objet contre des modifications
inappropriées
Souplesse
Le polymorphisme permet d'utiliser un même code sur des objets de
différentes classes
Factorisation
L'héritage permet de factoriser des données et instructions
Réutilisation
Les notions de classe et d'héritage permettent de réutiliser de
données

2
10/11/2020

2020-2021 Design Patterns 5

Limites des concepts objets de base


Ils ne permettent pas de garantir la conception de
programmes

maintenable
extensible
fiable

2020-2021 Design Patterns 6

Objectifs des concepts avancés


(facilement) Maintenable

(facilement) Extensible

Fiable

Réutilisable

3
10/11/2020

2020-2021 Design Patterns 7

Mise en œuvre
Programmation orientée objet SOLID

[R. C. Martin, 2002]

Design patterns (patrons de conception)

[E. Gamma, R. Helm,

R. Johnson et J. Vlissides, 1994]

2020-2021 Design Patterns 8

Principes de conception SOLID


 Responsabilité unique (Single responsability)
Une classe n'a qu'une responsabilité et ne doit avoir qu'une raison de changer

 Ouverture/fermeture (Open/Closed)
Une classe doit être ouverte aux extensions (ajouts) mais fermée aux modifications (du code
existant)

 Substitution de Liskov (Liskov substitution)


Un instance d'une classe doit pouvoir être substituée sans modification par une instance d'une
sous-classe

 Séparation des interfaces (Interfaces segregation)


Un client ne doit jamais être force de dépendre d'une interface qu'il n'utilise pas

 Inversion des dépendances (Dependency inversion)


Les modules (composants logiciels, classes..) de haut niveau ne doivent pas dépendre de
modules de bas niveau. Les deux doivent dépendre d'abstraction.

4
10/11/2020

2020-2021 Design Patterns 9

Principes de conception SOLID


Responsabilité unique (single responsability principle)
Enoncé:
« There should never be more than one reason for
a class to change »
(Il ne devrait jamais y avoir plus d’une raison de modifier une
classe).
C’est possible si la classe se focalise sur une seule
responsabilité, c’est-à-dire un seul objectif fonctionnel. Elle
possède alors une seule raison d’évoluer.
s’il existe plusieurs raisons de modifier une classe, il vaut
mieux la découper en plusieurs classes plus homogènes,
chacune conçue autour d’une responsabilité unique.

2020-2021 Design Patterns 10

Principes de conception SOLID


Responsabilité unique (single responsability principle)
Exemple: classe Image

5
10/11/2020

2020-2021 Design Patterns 11

Principes de conception SOLID


Responsabilité unique (single responsability principle)
Exemple: classe Image, classe AfficheurImage et EntreposeurImage

2020-2021 Design Patterns 12

Principes de conception SOLID


Responsabilité unique (single responsability principle)
Exemple: classe Image, classe AfficheurImage et EntreposeurImage

6
10/11/2020

2020-2021 Design Patterns 13

2020-2021 Design Patterns 14

Principes de conception SOLID


Ouvert-fermé (Open-closed principle)
Enoncé:
« Software entities (classes, modules, functions, etc.) should
be open for extension, but closed for modification »
(Les entités logicielles doivent être ouvertes aux extensions
et fermées aux modifications) [Mey98].
Concernant les classes, cela signifie qu’une classe doit
pouvoir être modifiée/étendue sans qu’il soit nécessaire
de toucher à son code.
En pratique, la modification prendra la forme d’un ajout de
classes, sans modifier celles qui existent déjà.
Dans le cas d’une bibliothèque, le principe ouvert-fermé
est satisfait si on ajoute une «nouvelle version» d’un
élément de la bibliothèque en cas d’évolution, plutôt que
de le modifier.

7
10/11/2020

2020-2021 Design Patterns 15

Principes de conception SOLID


Ouvert-fermé (Open-closed principle)
Pour les classes, l’héritage est le mécanisme essentiel
pour la mise en œuvre du principe, avec deux approches
possibles: l’héritage d’implantation et l’héritage
d’abstraction.

2020-2021 Design Patterns 16

Principes de conception SOLID


Ouvert-fermé (Open-closed principle)
Exemple:

Principe ”open-closed” : on doit pouvoir facilement ajouter des formes


a l’application sans modifier les classes existantes → principe respecté ?
NON : Editeur non fermé aux modifications si on ajoute une forme

8
10/11/2020

2020-2021 Design Patterns 17

Principes de conception SOLID


Ouvert-fermé (Open-closed principle)
Exemple: (solution)

On peut étendre le comportement


sans modifier le code : Editeur est
fermé aux modifications car la
méthode dessiner() ne change pas si
l’on ajoute une nouvelle Forme.
Editeur est ouverte aux extensions:
toutes les sous-classes de Forme
peuvent changer le comportement
de dessiner()

2020-2021 Design Patterns 18

Principes de conception SOLID


Ouvert-fermé (Open-closed principle)
Exemple:

9
10/11/2020

2020-2021 Design Patterns 19

Principes de conception SOLID


Ouvert-fermé (Open-closed principle)
Exemple: (Solution)

2020-2021 Design Patterns 20

Principes de conception SOLID


Substitution de Liskov (Liskov substitution principle)
Enoncé:
« If for each object o1 of type S there is an object o2 of type
T such that for all programs P defined in terms of T, the
behavior of P is unchanged when o1 is substituted for o2
then S is a subtype of T »
Un instance d'une classe doit pouvoir être substituée sans
modification par une instance d'une sous-classe (et sans que le
programme ne soit altéré dans son comportement)
Autrement dit :
Si une classe B hérite d’une classe A, tout programme écrit pour traiter
des instances de A doit pouvoir traiter des instances de B sans même
savoir que ce ne sont pas des instances directes de A.
Conséquences
Ne pas introduire de modifications dans le fonctionnement de B qui
rend inutilisable tout objet de type B utilisé comme un objet de type A.

10
10/11/2020

2020-2021 Design Patterns 21

Principes de conception SOLID


Substitution de Liskov (Liskov substitution principle)
Exemple:

2020-2021 Design Patterns 22

Principes de conception SOLID


Substitution de Liskov (Liskov substitution principle)
Exemple:

On peut obtenir parfois 100 au lieu de 50 ! Pourtant la Fabrique peut


tout à fait retourner un Carre, qui est un Rectangle dans la conception
utilisée. Et dans ce cas la méthode calculerAire va rendre 10*10

11
10/11/2020

2020-2021 Design Patterns 23

Principes de conception SOLID


Substitution de Liskov (Liskov substitution principle)
Solution proposée:
Pour factoriser malgré tout ce qui est commun, une solution peut
consister à définir une classe abstraite FormeRectangulaire dont
hérite Rectangle et Carre : les méthodes setLargeur, setHauteur,
setCote ne sont pas factorisées car ces méthodes n’ont pas de sens
pour un carré.

2020-2021 Design Patterns 24

Principes de conception SOLID


Substitution de Liskov (Liskov substitution principle)

12
10/11/2020

2020-2021 Design Patterns 25

Principes de conception SOLID


Substitution de Liskov (Liskov substitution principle)

2020-2021 Design Patterns 26

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Enoncé:
«High-level modules should not depend on low-
level modules. Both should depend on
abstractions. Abstractions should not depend upon
details. Details should depend upon abstractions»
• Les modules de haut niveau ne devraient pas dépendre
des modules de bas niveau. Les deux devraient dépendre
d’abstractions. Les abstractions ne devraient pas
dépendre des détails. Les détails devraient dépendre
d’abstractions

13
10/11/2020

2020-2021 Design Patterns 27

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Exemple: problème
Couche haut niveau
sont construits à partir
de modules fournissant
des services de bas
niveau

Couche bas niveau

Conséquences:
 Il faut modifier les modules de haut niveau quand les modules de bas
niveau évoluent.
 On ne peut pas réutiliser les modules de haut niveau (la logique « métier »)
dans un contexte technique autre que celui d’origine

2020-2021 Design Patterns 28

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Exemple: solution

Dans cette architecture, une couche


d’abstraction – interfaces ou classes abstraites
– est insérée pour séparer les deux niveaux.
 les dépendances sont alors inversées et
vont des modules du niveau bas vers les
interfaces (IHM et Com) du haut.
 La « couche métier » devient indépendante
de l’implantation des couches basses. Elle
ne dépend plus que de leurs interfaces. Elle
est donc réutilisable dans des contextes
différents

14
10/11/2020

2020-2021 Design Patterns 29

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Exemple: Cas général

Pour inverser la dépendance


entre deux classes A et B on
introduit une interface IB
(contenant les méthodes de
B que A peut appeler) dans
un paquet constitué de A et
IB

2020-2021 Design Patterns 30

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Exercice:

Un lecteur multimédia permet d’afficher des


fichiers PDF, d’écouter des fichiers MP3 et
de visualiser des DVD. La solution naïve fait
dépendre le lecteur multimédia des
différentes technologies. En cas de
modification ou d’extension de cette couche
basse, la classe de haut niveau doit être
modifiée.

Appliquer le principe d’inversion de


dépendance

15
10/11/2020

2020-2021 Design Patterns 31

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Exercice:

2020-2021 Design Patterns 32

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Exercice: Solution
La solution qui exploite l’inversion de dépendance introduit une couche
d’abstraction

16
10/11/2020

2020-2021 Design Patterns 33

Principes de conception SOLID


Inversion De Dépendance (Dependency inversion principle)
Exercice: Solution
La solution qui exploite l’inversion de dépendance introduit une couche
d’abstraction

2020-2021 Design Patterns 34

Principes de conception SOLID


Séparation des Interfaces (Interface segregation principle)
Enoncé:
«Clients should not be forced to depend upon
interfaces that they do not use»
Les clients ne devraient pas être forcés de dépendre
d’interfaces qu’ils n’utilisent pas

Eviter les « grosses interfaces » avec beaucoup de


méthodes pas toujours utiles pour toutes les classes ;
scinder ces « grosses interfaces » en interfaces plus
spécialisées et plus cohérentes.

17
10/11/2020

2020-2021 Design Patterns 35

Principes de conception SOLID


Séparation des Interfaces (Interface segregation principle)
Exemple:
Un jeu contient huit types de personnages. Pour traiter tous les
personnages de manière indifférenciée, le concepteur a prévu une
interface Personnage. Cette interface est complexe

2020-2021 Design Patterns 36

Principes de conception SOLID


Séparation des Interfaces (Interface segregation principle)
Exemple: solution améliorée
• Une conception moins naïve introduit des interfaces spécialisées
Consommateur et Acquereur

18
10/11/2020

2020-2021 Design Patterns 37

Design Patterns
Un patron décrit (et nomme) une
solution à un problème Commun
Offre une solution abstraite pour faciliter la
réutilisation
Est formulé en termes de classes et d’objets
Peut être implémenté différemment en
fonction du langage de programmation
utilisé
La solution proposée par un patron
peut être modifiée ou adaptée selon
les besoins du logiciel
« Forcer » l’utilisation d’un patron dans un
Référence de base de
logiciel est une mauvaise pratique de ce cours
développement

2020-2021 Design Patterns 38

Design Patterns
Les design patterns (patrons de conception)
décrivent des procédés généraux et réutilisables
pour concevoir des logiciels
Les design patterns mettent en œuvre les
principes SOLID
Un design pattern décrit une bonne pratique et
une solution standard en réponse à un problème
de conception d'un logiciel

19
10/11/2020

2020-2021 Design Patterns 39

Design Patterns
Types de patrons
Création (créer des objets)
Font l’abstraction du processus d’instanciation afin de rendre un système
indépendant de la façon dont ses objets sont créés et représentés
Patrons: Fabrique, Fabrique abstraite, Prototype, Singleton, Monteur
Structure (organiser les classes)
Se concentrent sur la façon dont les classes et les objets sont composés pour
obtenir de plus grandes structures
Patrons: Décorateur, Adapteur, Façade, Pont, Objet composite, Poids-
mouche, Proxy
Comportement (organiser la collaboration entre objets)
Décrivent les modèles de communication et interaction entres les objets
Patrons: Observateur, Stratégie, Commande, Médiateur, Chaîne de
responsabilité, Iterateur, Interpréteur, Etat, Patron de méthode, Visiteur, Fonction
de rappel

2020-2021 Design Patterns 40

Patron de conception Stratégie


Joël travaille pour une société qui a rencontré un énorme succès avec un jeu de
simulation de mare aux canards, SuperCanard. Le jeu affiche toutes les sortes de
canards qui nagent émettent des sons. Les premiers concepteurs du système ont utilisé
une superclasse Canard dont tous les autres types de canards héritent.

20
10/11/2020

2020-2021 Design Patterns 41

Patron de conception Stratégie

2020-2021 Design Patterns 42

Patron de conception Stratégie


 L’an passé, la société a subi de plus de pression de la
part de la concurrence.
 Pour battre cette concurrence, il faut une idée géniale:
les canards volants

21
10/11/2020

2020-2021 Design Patterns 43

Patron de conception Stratégie

2020-2021 Design Patterns 44

Patron de conception Stratégie


A la réunion de démonstration en présence des
actionnaires, Il y a plein de canards en plastique qui volent

22
10/11/2020

2020-2021 Design Patterns 45

Patron de conception Stratégie


 Une mise à jour locale du code a provoqué un effet de bord
global (des canards en plastique qui volent)!

2020-2021 Design Patterns 46

Patron de conception Stratégie


Joël réfléchit à l’héritage

23
10/11/2020

2020-2021 Design Patterns 47

Patron de conception Stratégie


 Les dirigeants ont décidé de réactualiser le produit tous les
six mois.
 Joël s’est rendu compte que l’héritage n’était pas probablement la
réponse.

2020-2021 Design Patterns 48

Patron de conception Stratégie


 Il doit modifier le comportement de vol dans les 48 sous
classes de canard qui volent
 Créer des sous-classes qui implémentent l’interface volant
ou cancaneur résout une partie de problème mais détruit la
réutilisabilité du code de ces comportements.

Un vrai cauchemar au
plan de la maintenance

24
10/11/2020

2020-2021 Design Patterns 49

Patron de conception Stratégie


 La seule constante entre tous le projet de développement
de logiciel c’est LE CHANGEMENT
 Une application qui n’évoluera pas au fil du temps, mourra.

Citer quelques facteurs qui peuvent motiver le changement?

2020-2021 Design Patterns 50

Patron de conception Stratégie


Principe de conception
Principe
Identifier les aspects de votre application qui varient et
séparez-les de ceux qui demeurent constants

Extraire les parties variables et les encapsuler vous


permettra plus tard de les modifier ou de les
augmenter sans affecter celles qui ne varient pas
 Tous les patterns fournissent un moyen de
permettre à une partie d’un système de varier
indépendamment de toutes les autres

25
10/11/2020

2020-2021 Design Patterns 51

Patron de conception Stratégie


 Appliquons ce principe au problème de superCanard!

2020-2021 Design Patterns 52

Patron de conception Stratégie


 Comment allons-nous procéder pour concevoir les classes
qui implémentent les deux types de comportement?
 Nous voulons affecter des comportements aux instances des classes
Canard.
 Modifier le comportement d’un canard dynamiquement avec les
méthodes set.( pouvoir modifier la façon de voler du canard au
moment de l’exécution)

Principe de conception
Principe Programmer une interface, non une implémentation

26
10/11/2020

2020-2021 Design Patterns 53

Patron de conception Stratégie


 Appliquons ce deuxième principe de conception

 Les comportements de Canard résideront


dans une classe distincte – une classe qui
Implémente une interface comportementale
particulière
 Les classes Canard n’auront besoin de
connaitre aucun détail de l’implémentation
de leur propre comportement.

2020-2021 Design Patterns 54

Patron de conception Stratégie


 Implémenter les comportements des canards

Les autres types d’objets peuvent


réutiliser nos comportements de vol et
de cancanement

On peut ajouter de nouveaux


comportements sans modifier aucune
des classes comportementales
existantes

27
10/11/2020

2020-2021 Design Patterns 55

Patron de conception Stratégie


 Intégrer les comportements des canards
Un canard va déléguer ses comportements au lieu d’utiliser les méthodes
voler() et cancaner() définies dans la classes canard ou ( une sous classes)

2020-2021 Design Patterns 56

Patron de conception Stratégie


 Intégrer les comportements des canards
Un canard va déléguer ses comportements au lieu d’utiliser les méthodes
voler() et cancaner() définies dans la classe canard ou ( une sous classes)

28
10/11/2020

2020-2021 Design Patterns 57

Patron de conception Stratégie


 Suite de l’intégration

2020-2021 Design Patterns 58

29
10/11/2020

2020-2021 Design Patterns 59

2020-2021 Design Patterns 60

 Vue d’ensemble des comportements encapsulés

30
10/11/2020

2020-2021 Design Patterns 61

 Diagramme de classes

2020-2021 Design Patterns 62

 Diagramme de classes

31
10/11/2020

2020-2021 Design Patterns 63

Patron de conception Stratégie


Principe de conception
Principe
Préférez la composition à l’héritage

Créer des systèmes en utilisant la composition


procure beaucoup plus de souplesse.
 Il ne permet non seulement d’encapsuler une
famille d’algorithmes, mais encore de modifier le
comportement au moment de l’exécution tant que
l’objet avec lequel il est composé implémente la
bonne interface comportementale.

2020-2021 Design Patterns 64

Patron de conception Observer


Type du pattern: comportemental

Nom: Observateur (Observer)

Thématique: dépendance de un à plusieurs


Raison d’être: définir une dépendance de un (observé) à
plusieurs (observateurs). Quand l’observé change d’état,
les observateurs qui se sont enregistrés auprès de lui
sont notifiés et mis à jour.

32
10/11/2020

2020-2021 Design Patterns 65

Patron de conception Observer


 Diagramme de classe

2020-2021 Design Patterns 66

Patron de conception Observer


Le diagramme UML du pattern Observateur définit deux interfaces et deux classes.
 Une interface Observateur sera implémenté par toutes les classes qui souhaitent avoir le rôle
d’observateur. C’est le cas de la classe ObservateurConcret qui implémente la méthode
actualiser(Observable). Cette méthode sera appelée automatiquement lors d’un changement
d’état de la classe observée.
 Une interface Observable qui devra être implémentée par les classes désireuses de posséder
des observateurs.
 La classe ObservableConcret implémente cette interface, ce qui lui permet de tenir informer
ses observateurs. Celle-ci possède en attribut un état (ou plusieurs) et un tableau
d’observateurs. L’état est un attribut dont les observateurs désirent suivre l’évolution de ses
valeurs. Le tableau d’observateurs correspond à la liste des observateurs qui sont à l’écoute.
En effet, il ne suffit pas à une classe d’implémenter l’interface Observateur pour être à l’écoute,
il faut qu’elle s’abonne à un Observable via la méthode ajouterObservateur(Observateur).

33
10/11/2020

2020-2021 Design Patterns 67

Patron de conception Observer


Le diagramme UML du pattern Observateur définit deux interfaces et deux classes.

 La classe ObservableConcret dispose de quatre méthodes que sont

ajouterObservateur(Observateur), supprimerObservateur(Observateur),
notifierObservateurs() et getEtat(). Les deux premières permettent, respectivement,
d’ajouter des observateurs à l’écoute de la classe et d’en supprimer.

 Le pattern Observateur permet de lier dynamiquement (faire une liaison lors de

l’exécution du programme par opposition à lier statiquement à la compilation) des


observables à des observateurs.

 La méthode notifierObservateurs() est appelée lorsque l’état subit un changement de

valeur. Celle-ci avertit tous les observateurs de cette mise à jour.

 La méthode getEtat() est un simple accesseur en lecture pour l’état. En effet, les

observateurs récupèrent via la méthode actualiser(Observable) un pointeur vers l’objet


observé. Puis, grâce à ce pointeur, et à la méthode getEtat() il est possible d’obtenir la
valeur de l’état.

2020-2021 Design Patterns 68

Patron de conception Observer


• Application

34
10/11/2020

2020-2021 Design Patterns 69

Patron de conception Observer


Vue d’ensemble de l’application
Les trois composants du système sont: ◦
 La station météo : Équipement physique qui recueille les données météo sur le temps.
 L’objet DonneesMeteo : qui mémorise les données provenant de la station et actualise
l’affichage.
 L’affichage lui-même que les utilisateurs consultent pour connaître les conditions
météorologiques actuelles.

2020-2021 Design Patterns 70

Patron de conception Observer


Vue d’ensemble de l’application
L’objet DonneesMeteo sait comment communiquer avec la station
physique pour obtenir les données à jour. Il actualise alors l’affichage de
trois éléments différents: Conditions actuelles (affiche la température,
l’hygrométrie et la pression atmosphérique), Statistiques et Prévisions.
Travail à réaliser:
Créer une application qui utilise l’objet DonnéesMéteo pour
actualiser les trois affichages:
• Conditions actuelles
• Statistiques
• Prévisions

35
10/11/2020

2020-2021 Design Patterns 71

Compléments: A l’intérieur de la classe DonneesMeteo

Notre tâche consiste à implémenter


la méthode actualiserMesures()
pour qu’elle mette à jour les trois
affichages: conditions actuelles,
statistiques et prévisions.

2020-2021 Design Patterns 72

Patron de conception Observer


Récapitulons…
La classe DonneesMeteo a des méthodes d’accès pour trois
valeurs de mesures: température, hygrométrie et pression
La méthode actualiserMesures() est appelée chaque fois
qu’une mesure est disponible.
Nous devons implémenter trois affichages qui utilisent les
données météorologiques: conditions actuelles, statistiques et
prévisions. Ils doivent être à jour chaque fois que
DonneesMeteo acquiert de nouvelles données
Le système doit être extensible: d’autres développeurs
pourront créer des affichages personnalisés et les utilisateurs
pourront ajouter ou retirer autant d’éléments qu’ils le
souhaitent à l’application.

36
10/11/2020

2020-2021 Design Patterns 73

Patron de conception Observer


Un premier essai : en suivant l’indication des dév. De MétéoExpress

Qu’est ce qui cloche dans


cette implémentation?

2020-2021 Design Patterns 74

Patron de conception Observer


Un premier essai : Qu’est ce qui cloche dans cette implémentation?

37
10/11/2020

2020-2021 Design Patterns 75

Patron de conception Observer


Faites connaissance avec le pattern Observateur
Vous savez comment fonctionne un abonnement à un journal ou à un magazine:
1. Un éditeur se lance dans les affaires et commence à diffuser des journaux.
2. Vous souscrivez à un abonnement. Chaque fois qu’il y a une nouvelle
édition, vous la recevez. Tant que vous êtes abonné, vous recevez de
nouveaux journaux.
3. Quand vous ne voulez plus de journaux, vous résiliez votre abonnement.
On cesse alors de vous les livrer.
4. Tant que l’éditeur reste en activité, les particuliers, les hôtels, les
compagnies aériennes, etc. ne cessent de s’abonner et de se désabonner.

2020-2021 Design Patterns 76

Diffusion+souscription= pattern observateur


Editeur = Sujet et les abonnés=les observateurs

38
10/11/2020

2020-2021 Design Patterns 77

Une journée dans la vie du pattern observateur

2020-2021 Design Patterns 78

Une journée dans la vie du pattern observateur

39
10/11/2020

2020-2021 Design Patterns 79

Une journée dans la vie du pattern observateur

2020-2021 Design Patterns 80

Une journée dans la vie du pattern observateur

40
10/11/2020

2020-2021 Design Patterns 81

Une journée dans la vie du pattern observateur

2020-2021 Design Patterns 82

Une journée dans la vie du pattern observateur

41
10/11/2020

2020-2021 Design Patterns 83

Une journée dans la vie du pattern observateur

2020-2021 Design Patterns 84

Une journée dans la vie du pattern observateur

42
10/11/2020

2020-2021 Design Patterns 85

Patron de conception Observer


Le pouvoir du couplage faible

Lorsque deux objets sont faiblement couplés, ils peuvent interagir

sans pratiquement se connaître.

Le pattern Observateur permet une conception dans laquelle le

couplage entre sujets et observateurs est faible.

Pourquoi?

2020-2021 Design Patterns 86

Patron de conception Observer


Le pouvoir du couplage faible

Le sujet ne sait qu’une seule chose à propos de l’observateur: il

implémente une certaine interface.

Nous pouvons ajouter des observateurs à tout moment.

Nous n’avons jamais besoin de modifier le sujet pour ajouter de

nouveaux type d’observateurs.

Nous pouvons réutiliser les objets et les sujets indépendamment les

uns des autres.

Les modifications des sujets n’affectent pas les observateurs et

inversement.

43
10/11/2020

2020-2021 Design Patterns 87

Patron de conception Observateur


Principe de conception
Principe
Efforcez-vous de coupler faiblement les objets
qui interagissent.

Les conceptions faiblement couplées permettent de


construire des systèmes orientés objets souples,
capables de faire face aux changements parce qu’ils
minimisent l’interdépendance entre les objets

2020-2021 Design Patterns 88

Patron de conception Observateur


Concevoir la station Météo

44
10/11/2020

2020-2021 Design Patterns 89

Implémenter la station Météo


// fichier Sujet.java
public interface Sujet {
public void enregistrerObservateur(Observateur o);
public void supprimerObservateur(Observateur o);
public void notifierObservateur();
}
----------------------------------------------------------------
// fichier Observateur.java
public interface Observateur {
public void actualiser(float temp,float humidite, float pression);
}
----------------------------------------------------------------
// fichier Affichage.java
public interface Affichage {
public void afficher();
}

2020-2021 Design Patterns 90

Implémenter l’interface Sujet dans DonneesMeteo


// fichier DonneesMeteo.java
import java.util.ArrayList;

public class DonneesMeteo implements Sujet {

private ArrayList<Observateur> observateurs;


private float temperature;
private float humidite;
private float pression;

public DonneesMeteo(){
observateurs=new ArrayList<Observateur>();
}

45
10/11/2020

2020-2021 Design Patterns 91

Implémenter l’interface Sujet dans DonneesMeteo


// Suite fichier DonneesMeteo.java
@Override
public void enregistrerObservateur(Observateur o) {
observateurs.add(o);
}
@Override
public void supprimerObservateur(Observateur o) {
int i=observateurs.indexOf(o);
if(i>=0) {observateurs.remove(i);}
}
@Override
public void notifierObservateur() {
for(int i=0;i<observateurs.size();i++){
Observateur observateur=(Observateur) observateurs.get(i);
observateur.actualiser(temperature,humidite,pression);
}
}

2020-2021 Design Patterns 92

Implémenter l’interface Sujet dans DonneesMeteo


// Suite fichier DonneesMeteo.java
public void actualiserMesures(){
notifierObservateur();
}

public void setMesures(float temperature, float humidite, float


pression) {
this.temperature=temperature;
this.humidite=humidite;
this.pression=pression;
actualiserMesures();
}
}

46
10/11/2020

2020-2021 Design Patterns 93

Maintenant, construisons les affichages


// fichier AffichageConditions.java
public class AffichageConditions implements Observateur, Affichage
{
private float temperature;
private float humidite;
private Sujet donneesMeteo;

public AffichageConditions(Sujet donneesMeteo){


this.donneesMeteo=donneesMeteo;
donneesMeteo.enregistrerObservateur(this);
}
@Override
public void afficher() {
System.out.println("Conditions actuelles :"+ temperature + "
degrés C et " + humidite +" d'humidité");
}

2020-2021 Design Patterns 94

Maintenant, construisons les affichages


// Suite fichier AffichageConditions.java
@Override
public void actualiser(float temp, float humidite, float pression)
{
temperature=temp;
this.humidite=humidite;
afficher();
}
}

47
10/11/2020

2020-2021 Design Patterns 95

Mettre en route la Station Météo


// fichier StationMeteo.java
public class StationMeteo {

public static void main(String[] args) {


DonneesMeteo donneesMeteo=new DonneesMeteo();

AffichageConditions afficheCond=new
AffichageConditions(donneesMeteo);

donneesMeteo.setMesures(26, 65, 1020);


donneesMeteo.setMesures(29, 70, 1012);
donneesMeteo.setMesures(22, 90, 1012);
}
}

2020-2021 Design Patterns 96

Implémentation en utilisant le pattern observer de Java


// fichier AffichageConditions.java
import java.util.Observable;
import java.util.Observer;

public class AffichageConditions implements Observer, Affichage {

private float temperature;


private float humidite;
Observable observable;

public AffichageConditions(Observable observable){


this.observable=observable;
observable.addObserver(this);
}

48
10/11/2020

2020-2021 Design Patterns 97

Implémentation en utilisant le pattern observer de Java


// Suite fichier AffichageConditions.java
@Override
public void afficher() {
System.out.println("Conditions actuelles :"+ temperature + "
degrés C et " + humidite +" d'humidité");
}
@Override
public void update(Observable obs, Object arg) {
if(obs instanceof DonneesMeteo) {
DonneesMeteo donneesMeteo = (DonneesMeteo) obs;
this.temperature=donneesMeteo.getTemperature();
this.humidite=donneesMeteo.getHumidite();
afficher();
}
}
}

2020-2021 Design Patterns 98

Implémentation en utilisant le pattern observer de Java


// fichier DonneesMeteo.java
import java.util.Observable;

public class DonneesMeteo extends Observable {

private float temperature;


private float humidite;
private float pression;

public DonneesMeteo(){
}
public void actualiserMesures(){
setChanged();
notifyObservers();
}

49
10/11/2020

2020-2021 Design Patterns 99

Implémentation en utilisant le pattern observer de Java


// Suite fichier DonneesMeteo.java
public void setMesures(float temperature, float humidite, float
pression) {
this.temperature=temperature;
this.humidite=humidite;
this.pression=pression;
actualiserMesures();
}
public float getTemperature() {
return temperature;
}
public float getHumidite() {
return humidite;
}
public float getPression() {
return pression;
}
}

2020-2021 Design Patterns 100

Patron de conception Fabrique


(factory)
Motivations

Des conceptions problématiques


Une mauvaise conception

Une meilleure conception

La meilleure conception : Le patron de conception


"Fabrique"
L’exemple de la pizzeria

Le patron de conception

Principes SOLID mis en œuvre

50
10/11/2020

2020-2021 Design Patterns 101

Patron de conception Fabrique


Motivations
Fabriquer des objets sans spécifier leurs types concrets

On veut fabriquer toutes sortes de pizzas, sans avoir à modifier la


classe Pizzeria si on crée de nouvelles Pizzas ou qu’on élimine
certaines Pizzas

2020-2021 Design Patterns 102

Patron de conception Fabrique


Conception naïve
Fabriquer des objets sans spécifier leurs types concrets

On contrevient au principe SOLID : ouvert à l’extension et fermé à


la modification. La classe Pizzeria ne doit pas changer si l’on modifie
le type des pizzas.

51
10/11/2020

2020-2021 Design Patterns 103

Patron de conception Fabrique


Conception améliorée
On déporte la création des Pizzas dans une autre classe

2020-2021 Design Patterns 104

Patron de conception Fabrique


Conception améliorée
On déporte la création des Pizzas dans une autre classe

52
10/11/2020

2020-2021 Design Patterns 105

Patron de conception Fabrique


L’exemple de Pizzeria
On crée plusieurs fabriques de Pizzas

Souplesse : On peut créer plusieurs


Pizzas, chacune de plusieurs façons

2020-2021 Design Patterns 106

Patron de conception Fabrique


L’exemple de Pizzeria
On crée plusieurs fabriques de Pizzas (Java)

53
10/11/2020

2020-2021 Design Patterns 107

Patron de conception Fabrique


L’exemple de Pizzeria
On crée plusieurs fabriques de Pizzas (Java)

2020-2021 Design Patterns 108

Patron de conception Fabrique


Définition

Le patron de conception Fabrique définit une interface pour


la création d’un objet laissant aux sous-classes le choix
des classes à instancier
Fabrique permet à une classe de déléguer l’instanciation à
des sous-classes.

54
10/11/2020

2020-2021 Design Patterns 109

Patron de conception Fabrique


Structure du patron de conception Fabrique

2020-2021 Design Patterns 110

Patron de conception Fabrique


Principes SOLID mis en oeuvre
Open-close (SOLID) :
Les classes doivent être ouvertes à l’extension mais fermées à la modification.
principe de fermeture à la modification : on a déporté la création concrète
des Pizzas dans une autre classe pour ne pas modifier Pizzeria si d’autres
types de Pizzas étaient développées ou si certaines Pizzas devaient
disparaître.
Dependency inversion (SOLID) :
Les modules (composants logiciels, classes..) de haut niveau ne doivent pas dépendre des
modules de bas niveau. Les deux doivent dépendre d’abstraction.
principe d’inversion des dépendances : on évite le couplage fort.

55
10/11/2020

2020-2021 Design Patterns 111

Patron de conception Fabrique


Principes SOLID mis en oeuvre
Couplage fort
Le couplage est une mesure de la dépendance entre classes. Le couplage d’une classe doit être le plus faible possible.

Pizzeria crée les Pizzas : elles dépend donc de toutes les classes décrivant
les Pizzas, un changement dans l’une d’elle oblige à modifier Pizzeria.

2020-2021 Design Patterns 112

Patron de conception Fabrique


Principes SOLID mis en oeuvre
Inversion des dépendances
les modules (composants logiciels, classes..) de haut niveau ne doivent pas dépendre des modules de bas niveau. Les deux
doivent dépendre d’abstraction.

Grâce au pattern Fabrique la classe Pizzeria ne dépend plus que de la classe Pizza.
On peut donc facilement créer/retirer des Pizzas sans modifier Pizzeria.

56
10/11/2020

2020-2021 Design Patterns 113

Problème Pizzeria

2020-2021 Design Patterns 114

Problème de Pizzeria
un seul pizza ne suffit pas
• Mais un seul type de pizza ne suffit pas...

57
10/11/2020

2020-2021 Design Patterns 115

Problème de Pizzeria
Rester en concurrence

2020-2021 Design Patterns 116

Problème de Pizzeria
Encapsuler la création des objets

58
10/11/2020

2020-2021 Design Patterns 117

Problème de Pizzeria
Encapsuler la création des objets - Fabrique

2020-2021 Design Patterns 118

Problème de Pizzeria
Construire une simple fabrique de Pizza

59
10/11/2020

2020-2021 Design Patterns 119

Problème de Pizzeria
Retravailler la classe Pizzeria

2020-2021 Design Patterns 120

Problème de Pizzeria
Fabrique Simple

60
10/11/2020

2020-2021 Design Patterns 121

Problème de Pizzeria
Franchiser les pizzerias

2020-2021 Design Patterns 122

Problème de Pizzeria
Franchiser les pizzerias

61
10/11/2020

2020-2021 Design Patterns 123

Problème de Pizzeria
Mais le contrôle qualité vous semble légèrement
insuffisant...

Les pizzeria franchisées avaient


un mode de cuisson un peu
différent Elles oubliaient de
couper la pizza et achetaient
leurs boîtes à d’autres
fournisseurs.

2020-2021 Design Patterns 124

Problème de Pizzeria
Une structure pour la Pizzeria

62
10/11/2020

2020-2021 Design Patterns 125

Problème de Pizzeria
Une structure pour la Pizzeria

2020-2021 Design Patterns 126

Problème de Pizzeria
Pattern Fabrication – Créateur (facteur)

63
10/11/2020

2020-2021 Design Patterns 127

Problème de Pizzeria
Pattern Fabrication – Classes produits

2020-2021 Design Patterns 128

Problème de Pizzeria
Pattern Fabrication – Définition

64
10/11/2020

2020-2021 Design Patterns 129

Fabrique Abstraite
Anglais: Abstract factory, Kit
Synonyme: -
Catégorie: pattern de construction
Thématique: Fabrication de familles d’objets, Dépendance
à leurs classes concrètes
Définition:
Le pattern Décorateur attache dynamiquement des
responsabilités supplémentaires à un objet. Il fournit une
alternative souple à la dérivation, pour étendre les
fonctionnalités.

2020-2021 Design Patterns 130

Revenons à l’exemple de Pizzeria


Pizzeria très dépendante
Sans appliquer la méthode de fabrication notre classe
ressemblera à:

65
10/11/2020

2020-2021 Design Patterns 131

Revenons à l’exemple de Pizzeria


Pizzeria très dépendante
Diagramme traçant les dépendances de Pizzeria

2020-2021 Design Patterns 132

Revenons à l’exemple de Pizzeria


Le principe d’inversion des dépendances
Pour réduire les dépendances, Il y a un principe de
conception OO.
Principe de conception
Dépendez d’abstractions. Ne dépendez pas de classes concrètes
Principe

Module de
haut niveau

Module de
bas niveau

66
10/11/2020

2020-2021 Design Patterns 133

Revenons à l’exemple de Pizzeria


Appliquer le principe
En appliquant le principe permet de dépendre à une
abstraction mais le problème des instanciations persiste
dans la méthode commanderPizza()?
Le pattern Fabrication résout le problème Module de
haut niveau

Couche
d’abstraction

Module de
bas niveau

2020-2021 Design Patterns 134

Conseils pour ioc


Appliquer le principe
• Aucune variable ne doit contenir une référence à une
classe concrète.
• Utiliser une fabrication au lieu de l’opérateur new
• Aucune classe ne doit dériver d’une classe concrète
• Sous-classez une abstraction plutôt qu’une classe concrète
• Aucune classe ne doit redéfinir une méthode
implémentée dans une classe de base
• Une méthode définie dans une classe de base est pour être
partagée par toutes les sous-classes.

67
10/11/2020

2020-2021 Design Patterns 135

Retour au problème du pizzeria


Qualité des garnitures

• La clé du succès de la boutique est la


qualité et la fraicheur d’ingrédients.
• Les franchises appliquent bien les
procédures de la boutique mère, mais
elles commencent à substituer les
garnitures d’origine par d’autres de
qualité inférieur pour diminuer les coûts
et augmenter leurs marges.

2020-2021 Design Patterns 136

Retour au problème du pizzeria


Assurer la cohérence des garnitures

• Comment veiller à la qualité des garnitures utilisées par


les franchises?
• Construire une fabrique qui les produit et qui les leur
expédie?!
• Les franchises sont dispersés dans les différentes
régions?
• En plus une sauce tomate de Casablance n’est pas
celui de Marrakech

68
10/11/2020

2020-2021 Design Patterns 137

Retour au problème du pizzeria


Famille de garnitures

Toutes les pizza de la boutique mère sont


fabriquées à partir des mêmes
composants, mais chaque région a une
implémentation différente de ces
composants

2020-2021 Design Patterns 138

Retour au problème du pizzeria


Construction des fabriques d’ingrédients

69
10/11/2020

2020-2021 Design Patterns 139

Retour au problème du pizzeria


Construction fabrique de Brest comme exemple

La fabrique de Brest
est spécialisée dans
la sauce Marinara, le
parmigiano reggiano,
les moules fraîches..

2020-2021 Design Patterns 140

Retour au problème du pizzeria


Retravailler les pizzas Chaque pizza contient un
ensemble d’ingrédients
utilisés dans sa
préparation

La fonction preparer()
est abstraite et c’est les
sous classes ou nous
allons collecter les
ingrédients nécessaires
pour la pizza à travers la
fabrication d’ingrédients

70
10/11/2020

2020-2021 Design Patterns 141

Retour au problème du pizzeria


Retravailler les pizzas
Chaque pizza utilise une fabrication
d’ingrédients qui passé au
constructeur de la classe et stocké
dans une variable d’instance

La méthode preparer()
parcourt les étapes de la
création d’une pizza au
fromage. Chaque fois
besoin d’un ingrédient,
elle demande à la
fabrication

2020-2021 Design Patterns 142

Retour au problème du pizzeria


Retravailler les pizzas
Nous affectons à la variable
d’instance de Pizza une
référence à la sauce spécifique
utilisée dans cette pizza

Fabrique d’ingrédients La méthode creerSauce()


retourne la sauce
employée dans sa région

71
10/11/2020

2020-2021 Design Patterns 143

Retour au problème du pizzeria


Retravailler les pizzas

2020-2021 Design Patterns 144

Retour au problème du pizzeria


Revisitons les pizzerias

72
10/11/2020

2020-2021 Design Patterns 145

Retour au problème du pizzeria


Revisitons les pizzerias

2020-2021 Design Patterns 146

Retour au problème du pizzeria


Revisitons les pizzerias

73
10/11/2020

2020-2021 Design Patterns 147

Retour au problème du pizzeria


Revisitons les pizzerias

2020-2021 Design Patterns 148

Le pattern Fabrique Abstraite


Définition

74
10/11/2020

2020-2021 Design Patterns 149

Le pattern Fabrique Abstraite


Définition

2020-2021 Design Patterns 150

Le pattern Fabrique Abstraite


Définition

75
10/11/2020

2020-2021 Design Patterns 151

Décorateur (Decorator)
Anglais: Decorator, wrapper
Synonyme: -
Catégorie: pattern de structure
Thématique: Ajout de propriétés sans écrire une sous-
classe
Définition:
Le pattern Décorateur attache dynamiquement des
responsabilités supplémentaires à un objet. Il fournit une
alternative souple à la dérivation, pour étendre les
fonctionnalités.

2020-2021 Design Patterns 152

Diagramme de classe
class Pattern Decorateur

Composant
+ methodeA()
+ methodeB()
+ //autres méthodes()

ComposantConcret Decorateur
+ methodeA() + methodeA()
+ methodeB() + methodeB()
+ //autres méthodes() + //autres méthodes()

DecorateurConcretB
DecorateurConcretA
- ObjetEnveloppe: Composant
- ObjetEnveloppe: Composant
- NewState: Object
+ methodeA()
+ methodeA()
+ methodeB()
+ methodeB()
+ //autres méthodes()
+ //autres méthodes()

76
10/11/2020

2020-2021
class Pattern Decorateur Design Patterns 153

Chaque composant peut être


utilisé seul ou enveloppé par
un décorateur.

Composant
+ methodeA()
+ methodeB() Chaque décorateur A-UN (enveloppe) un
+ //autres méthodes() composant, ce qui signifie qu’il a une
variable d’instance qui contient une
référence à un composant.

Le ComposantConcret est
l’objet auquel nous allons
ajouter dynamiquement un
ComposantConcret Decorateur
nouveau comportement. Il Les décorateurs implémentent
dérive de Composant. + methodeA() + methodeA() la même interface ou classe
+ methodeB() + methodeB() abstraite que le composant
qu’ils vont décorer.
+ //autres méthodes() + //autres méthodes()

Le DecorateurConcret a une variable DecorateurConcretB


d’instance pour l’objet qu’il décore (le
DecorateurConcretA
Les décorateurs
Composant que le Décorateur - ObjetEnveloppe: Composant
enveloppe). - ObjetEnveloppe: Composant peuvent étendre
- NewState: Object l’état du composant.
+ methodeA()
+ methodeA()
+ methodeB()
+ methodeB()
+ //autres méthodes()
+ //autres méthodes()

Les Décorateurs peuvent ajouter de


nouvelles méthodes, mais on ajoute
généralement le nouveau comportement
en effectuant un traitement avant ou après
une méthode existant dans le composant.

2020-2021 Design Patterns 154

Exemple tiré de Java

 Le patron Décorateur est utilisé par Java pour construire les flux
d’entrée/sortie complexes.
• Par exemple, un java.io.BufferedReader est un décorateur qui décore
(enveloppe) un java.io.FileReader en lui ajoutant la méthode public
String readLine() permettant de lire une ligne de texte. Le FileReader
ne sait à la base lire que caractère par caractère avec public int
read().

77
10/11/2020

2020-2021 Design Patterns 155

Exemple tiré de Java

 Le patron Décorateur est utilisé par Java pour construire les flux
d’entrée/sortie complexes.
• Par exemple, un java.io.BufferedReader est un décorateur qui décore
(enveloppe) un java.io.FileReader en lui ajoutant la méthode public
String readLine() permettant de lire une ligne de texte. Le FileReader
ne sait à la base lire que caractère par caractère avec public int
read().

78

Vous aimerez peut-être aussi