0% ont trouvé ce document utile (0 vote)
71 vues99 pages

Introduction aux Patrons de Conception

Transféré par

trankhanhdan1999
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)
71 vues99 pages

Introduction aux Patrons de Conception

Transféré par

trankhanhdan1999
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

Patrons de Conception

(Design Patterns)
Nan MESSE
[email protected]
Rappel des concepts fondamentaux de l’Orienté Objet

- Classe
- Objet

2
Abstraction

- L’abstraction est la modélisation d’un


objet ou phénomène du monde réel,
limité à un contexte spécifique dont on
relève tous les détails utiles avec une
grande précision, et dont on ignore le
reste.

3
Encapsulation

- L’encapsulation est la technique qu’un objet utilise pour cacher une partie de son état et de ses
comportements aux autres objets, pour ne révéler qu’une interface limitée au reste du programme.
- private ou protected

4
Héritage

- L’héritage permet de construire de nouvelles classes à partir de classes existantes. Il favorise la


réutilisation du code.
- Si une classe mère implémente une interface, toutes ses sous-classes doivent également
l’implémenter

5
Polymorphisme

- Le polymorphisme est la capacité d’un programme à détecter la classe d’un objet et à appeler son
implémentation, même si son type est inconnu dans le contexte actuel.

6
Héritage et Composition

7
Couplage fort

Quand une classe A est lié à une classe B, on dit que


la classe A est fortement couplée à la classe B.
La classe A ne peut fonctionner qu’en présence de la
classe B.
Si une nouvelle version de la classe B (soit B2), est
créé, on est obligé de modifier les codes dans la
classe A.
Modifier une classe implique :
- Il faut disposer du code source.
- Il faut recompiler, déployer et distribuer la
nouvelle application aux clients.
- Ce qui engendre un cauchemar au niveau de la
maintenance de l’application.

8
Couplage faible

- Pour utiliser le couplage faible, nous devons utiliser


les interfaces.
- Considérons une classe A qui implémente une interface IA,
et une classe B qui implémente une interface IB.
- Si la classe A est liée à l’interface IB par une association,
on dit que la classe A et la classe B sont liées par un
couplage faible.
- Cela signifie que la classe A peut fonctionner avec
n’importe quelle classe qui implémente l’interface IB.
- En effet, la classe A ne connait que l’interface IB. De ce fait,
n’importe quelle classe implémentant cette interface peut être
associée à la classe A, sans qu’il soit nécessaire de modifier
quoi que ce soit dans la classe A.
- Avec le couplage faible, nous pourrons créer des applications
fermées à la modification et ouvertes à l’extension.

9
Pourquoi l’approche Orientée Objet a été créée ?

- Pour faciliter la réutilisation de l’expérience des autres :


- Créer des applications faciles à maintenir :
- Applications fermées à la modification et ouvertes à l’extension
- Créer des applications performantes
- Créer des applications sécurisées
- Créer des applications distribuées
- Séparer les différents aspects d’une application :
- Aspects Métiers (fonctionnels)
- Aspect Présentation (Web, Mobile, Desktop, …)
- Aspect Techniques

10
● Réutilisation du code

+ réduire le coût et le temps


- adapter le code à un nouveau
contexte demande un certain travail :
Caractéristiques -
-
les composants fortement couplés
les dépendances aux classes

d’une bonne -
concrètes
les codes écrit en dur…

conception ⇾ manque de flexibilité

● Extensibilité

+ répondre aux changements

11
● Encapsuler ce qui varie et le séparer
de ce qui est statique

+ minimiser les effets causés par toute

Principes de +
modification
au niveau méthode et classe
● Programmer avec les interfaces, et
conception non pas avec les implémentations

+ Dépendre des abstractions, pas des


classes concrètes

12
● Encapsuler ce qui varie et le séparer
de ce qui est statique

+ minimiser les effets causés par toute


modification
+ au niveau méthode et classe
● Programmer avec les interfaces, et
non pas avec les implémentations

+ Dépendre des abstractions, pas des


classes concrètes

13
● Encapsuler ce qui varie et le séparer
de ce qui est statique

+ minimiser les effets causés par toute


modification
+ au niveau méthode et classe
● Programmer avec les interfaces, et
non pas avec les implémentations

+ Dépendre des abstractions, pas des


classes concrètes

14
● Encapsuler ce qui varie et le séparer
de ce qui est statique

+ minimiser les effets causés par toute


modification
+ au niveau méthode et classe
● Programmer avec les interfaces, et
non pas avec les implémentations

+ Dépendre des abstractions, pas des


classes concrètes

15
● Encapsuler ce qui varie et le séparer
de ce qui est statique

minimiser les effets causés par toute


Principes de
+
modification
+ au niveau méthode et classe

conception ● Programmer avec les interfaces

○ Dépendre des abstractions, pas des


classes concrètes

Extensibilité Flexibilité

16
La classe Société est toujours couplée aux classes des employés. Nous allons nous retrouver en mauvaise posture si nous devons
ajouter de nouveaux types de sociétés qui hébergent d’autres types d’employés, car nous allons devoir redéfinir la majeure partie de la
classe Société, plutôt que de réutiliser pour son code.
17
Fabrique

Maintenant, la classe
Société est devenue
indépendante des diverses
classes des employés.
Vous pouvez désormais l’
étendre et introduire de
nouveaux types de
sociétés et d’employés,
tout en réutilisant une
partie du code de la classe
de base société. Étendre la
classe de base société ne
modifie pas le code
existant qui en dépend.

18
● Préférer la composition à l’héritage

- Une sous-classe ne peut pas réduire la


taille de l’interface de la classe mère
- Lorsque vous redéfinissez des méthodes,
vous devez vous assurer que leur
comportement est compatible avec la
Principes de -
classe de base
L’héritage détruit l’encapsulation de la

conception -
classe mère
Les sous-classes sont fortement couplées
aux classes mères : la moindre
modification de la classe mère peut
impacter le fonctionnement de ses
sous-classes
- Peut avoir une explosion combinatoire de
sous-classes
19
Stratégie

Cette technique vous permet même de modifier le


comportement lors de l’exécution. Vous pouvez par
exemple remplacer un objet moteur associé à un objet
voiture, en assignant un moteur différent à la voiture. 20
Histoire

● introduit par Christopher Alexander dans “A Pattern Language: Towns, Buildings, Construction”
● 1977

● repris par Erich Gamma, John Vlissides, Ralph Johnson, et Richard Helm
● dans “Design Patterns: Elements of Reusable Object-Oriented Software”
● 1994, 23 patrons
● remplacé par “the book by the Gang of Four”, puis “the GoF book”
Collections
● Pattern-Oriented Software Architecture, Volume 1: A System of Patterns des
● 1996 Patrons
● Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad and
Michael Stal
● POSA1 book
Ce sont des solutions classiques à des problèmes connus en conception orientée objet.
Lorsqu’une question revient encore et encore dans différents projets, quelqu’un se
décide finalement à détailler la solution et à lui donner un nom. C’est souvent comme 21
cela qu’un patron est découvert.
Patron de Conception (Design Pattern) - Définition

Les patrons de conception sont des solutions classiques à des problèmes récurrents de la
conception de logiciels [1].

Un patron n’est pas un bout de code spécifique, mais plutôt un concept général pour résoudre un
problème précis.

Chaque patron est une sorte de plan ou de schéma que vous pouvez personnaliser afin de
résoudre un problème récurrent dans votre code.

recopier suivre le principe du patron


et implémenter une solution

22
Pourquoi apprendre les patrons ?
● Une boîte à outils de solutions fiables et éprouvées permettant de
résoudre des problèmes classiques de la conception de logiciels.
● Une identification et spécification d’abstractions qui sont au-dessus du
niveau des simples classes et instances (s’applique aux différents
scénarios).
● Un vocabulaire commun de se communiquer -> “Oh, tu n’as qu’à utiliser un
singleton”.
● Un moyen de documentation de logiciels.
● Une aide à la construction de logiciels complexes et hétérogènes,
répondant à des propriétés précises. 23
Patrons vs. Algorithmes ?

Patron Algorithme

décrivent des solutions classiques à des problèmes connus

décrit une solution à un plus haut niveau définit toujours clairement un ensemble
d’actions qui va vous mener vers un objectif
Le code utilisé pour implémenter un même précis
patron peut être complètement différent s’il
est appliqué à deux programmes distincts

Un plan, reproductible dans tous les Une recette de cuisine, ses étapes sont
contextes claires
24
Classification des Design Patterns

● Patrons de création : fournissent des mécanismes de création d’objets (ce


qui augmente la flexibilité et la réutilisation du code)
○ montre quelle est la façon la plus adéquate d’instancier des objets, comment on va les
créer, initialiser, configurer ces objets.
○ new peut être dangereux, vous pouvez créer bcp d’objets que vous ne les utilisez pas,
risquez de surcharger la mémoire avec bcp d’instance, fuite mémoire, pb de maintenance.
○ Le principe de ces patrons de création est d’isoler les codes relatifs à la création des
objets, afin de l’application indépendante de l’évolution future.
● Patrons structurels : expliquent comment assembler des objets et des
classes en de plus grandes structures - Éviter des couplages forts
○ montre comment connecter les objets, de façon qu’on aille rendre ces connections
indépendante ou résisté au changement ou à l'évolution future de l’application
○ On ne va pas s’intéresser à la dynamique du système (au moment de l’exécution, comment
les objets vont interagir), l’aspect statique, diag. classe
● Patrons comportementaux : mettent en place une interaction efficace et
répartissent les responsabilités entre les objets. (diag. séquence) 25
Portée des Design Patterns

- Portée de Classe
- Focalisation sur les relations entre classes et leurs sous-classes
- Réutilisation par héritage

- Portée d’Instance (Objet)


- Focalisation sur les relations entre les objets
- Réutilisation par composition

26
23 Patrons GoF

27
https://slideplayer.com/slide/6667469/
Patrons POSA1

Exprime un schéma d'organisation Fournit un schéma pour affiner les


structurel fondamental pour un composants d'un système logiciel
système logiciel ou les relations entre eux.

Architecture Patterns Design Patterns

Layers Whole-Part

Pipes & Filters Master-Slave

Blackboard Proxy

Broker Command Processor

Model-View-Controller View handler

Presentation-Abstraction-Control Forwarded-Receiver

Microkernel Client-Dispatcher-Server
28
Reflection Publisher-Subscriber
Présentation d’un Design Pattern

● Nom du patron
○ utilisé pour décrire le patron, ses solutions et les conséquences en un mot ou deux
● Problème
○ description des conditions d’applications. Explication du problème et de son contexte
● Solution
○ description des éléments (objets, relations, responsabilités, collaboration)
○ permettant de concevoir la solution au problème ; utilisation des diag. de classes, de
séquences, …
○ vision statique ET dynamique de la solution
● Conséquences
○ description des résultats (effets induits) de l’application du patron sur le système (positifs
ET négatifs)

29
● Fabrique (Factory Method)
GoF
● Fabrique abstraite (Abstract
Factory)
Patrons de création
● Monteur (Builder)
fournissent des mécanismes de
création d’objets (ce qui augmente la ● Prototype
flexibilité et la réutilisation du code)
● Singleton

30
Singleton

Singleton garantit la création d’une instance unique d’une classe durant toute la durée
d’exécution d’une application, tout en fournissant un point d’accès global à cette
instance.

Objectifs : Il garantit l’unicité d’une instance pour une classe et il fournit un point
d’accès global (une méthode) à cette instance.

Le singleton vous permet d’accéder à l’objet n’importe où dans le programme, telle une
variable globale. Cependant, il protège son instance et l’empêche d’être modifiée.

On l’utilise lorsqu’on veut contrôler l’accès à une ressource partagée, par ex. 31
Singleton - Solution, Analogie et Structure

- Rendre le constructeur par défaut privé afin d’empêcher les autres objets d’utiliser
l’opérateur new avec la classe du singleton
- Mettre en place une méthode de création statique qui se comporte comme un
constructeur. Cette méthode appelle le constructeur privé pour créer un objet et le
sauvegarde dans un attribut statique. Tous les appels ultérieurs à cette méthode
retournent l’objet en cache.
- Exemple : gouvernement

Si votre code a accès à la classe du singleton, alors il peut appeler sa


méthode statique. À chaque appel de cette méthode, c’est toujours le même
objet qui est retourné.
La classe Singleton déclare la méthode statique getInstance qui retourne la
même instance de sa propre classe.
Le code client ne doit pas avoir de visibilité sur le constructeur du singleton.
Seule la méthode getInstance doit permettre l’accès à l’objet du singleton.
32
Cette méthode crée un objet ou retourne l’objet existant s’il a déjà été créé.
Singleton - Pseudo-code avec un exemple bdd

La classe de la
connexion à la base de
données est le Singleton.
Cette classe n’a pas de
constructeur public, vous
ne pouvez y accéder que
grâce à la méthode
getInstance.
Cette méthode met en
cache le premier objet
créé puis retourne ce
même objet lors des
appels ultérieurs.

33
Singleton - Pseudo-code avec un exemple bdd

34
Singleton - Possibilités d’application

- Utilisez le singleton lorsque l’une de vos classes ne doit fournir qu’une seule instance à tous
ses clients.
- Ex. une base de données partagée entre toutes les parties d’un programme.
- La méthode spéciale de création devient le seul moyen de fabriquer des objets pour la
classe, car le singleton désactive les autres. Cette méthode crée un objet ou retourne
l’objet existant s’il a déjà été créé.

- Utilisez le singleton lorsque vous voulez un contrôle absolu sur vos variables globales.

- Exercice : https://www.wooclap.com/L3502
35
● Adaptateur (Adapter)

● Pont (Bridge)
GoF
● Composite
Patrons Structurels ● Décorateur (Decorator)
expliquent comment assembler des ● Façade (Facade)
objets et des classes en de plus
grandes structures ● Poids mouche (Flyweight)

● Procuration (Proxy)

36
Composite

Composite permet d’organiser les objets en structure arborescente afin de


représenter une hiérarchie.

Ce patron permet à la partie cliente de manipuler un objet unique et un objet


composé de la même manière.

L’utilisation de ce patron doit être réservée aux applications dont la structure


principale peut être représentée sous la forme d’une arborescence.

37
Composite - Calculer le coût total d’une commande

Pour un produit, on retourne simplement son prix. Pour une boîte, on parcourt chacun
de ses objets, on leur demande leur prix, puis on retourne un total pour la boîte. Si l’un
de ces objets est une boîte plus petite, cette dernière va aussi parcourir son propre
contenu et ainsi de suite, jusqu’à ce que tous les prix aient été calculés.

Vous n’avez même pas besoin de connaître la classe concrète des objets de
l’arborescence.

Vous n’avez pas besoin de savoir si un objet est un produit tout simple ou une boîte
sophistiquée, vous les manipulez de la même manière grâce à une interface commune.
Lorsque vous faites appel à une méthode, les objets s’occupent de faire transiter la
requête en descendant vers les feuilles de l’arbre. 38
Composite - Structure

1. L’interface Composant décrit les opérations communes


aux objets simples et complexes de l’arborescence.
2. Une Feuille est un élément de base d’une branche qui n’a
pas de sous-élément.
3. Le Conteneur (alias composite) est un élément composé
de sous-éléments : des feuilles ou d’autres conteneurs. Un
conteneur ne connaît pas les classes de ses enfants. Il
passe par l’interface composant pour interagir avec ses
sous-éléments.
4. Le Client manipule les éléments depuis l’interface
composant, ce qui lui permet de fonctionner de la même
manière pour les éléments simples et complexes de
l’arborescence.

39
Composite - Exemple de l’éditeur des formes géométriques

40
41
42
43
Composite - Possibilités d’application

- Utilisez le composite si vous devez gérer une structure d’objets qui ressemble à une
arborescence.

- Utilisez ce patron si vous voulez que le client interagisse avec les éléments simples aussi
bien que complexes de façon uniforme.

- Exercice : https://www.wooclap.com/EPIRIZ

44
● Chaîne de Responsabilité (Chain of Responsability)

● Commande (Command)

GoF ● Itérateur (Iterator)

● Médiateur (Mediator)
Patrons ● Mémento (Memento)
Comportementaux ● Observateur (Observer)

mettent en place une communication ● État (State)

efficace et répartissent les ● Stratégie (Strategy)


responsabilités entre les objets
● Patron de Méthode (Template Method)

● Visiteur (Visitor)

45
Observer
L’Observateur permet de mettre en place un mécanisme de souscription pour
envoyer des notifications à plusieurs objets, au sujet d’événements concernant
les objets qu’ils observent.

Soit les clients perdent leur temps à venir vérifier la disponibilité des produits, soit le magasin gâche des ressources pour prévenir des clients qui ne sont pas concernés.
46
Observer

- L’objet que l’on veut suivre est en général appelé sujet, mais comme il va
envoyer des notifications pour prévenir les autres objets dès qu’il est
modifié, nous l’appellerons diffuseur (publisher). Tous les objets qui
veulent suivre les modifications apportées au diffuseur sont appelés des
souscripteurs (subscribers) -> relation un à plusieurs.
- Le patron Observateur vous propose d’ajouter un mécanisme de
souscription à la classe diffuseur pour permettre aux objets individuels de
s’inscrire ou se désinscrire de ce diffuseur.
- À chaque fois que l’état de diffuseur change, tout ce qui en dépendent en
soient informés et soient mis à jour automatiquement.

47
Push and Pop : 2 moyens d’observer

Push to observers model Pop to observers model

48
Observer

Ce mécanisme est composé :


1) d’un tableau d’attributs qui stocke
une liste de références vers les
objets souscripteur
2) de plusieurs méthodes publiques qui
permettent d’ajouter ou de supprimer
des souscripteurs de cette liste.

Quand un événement important arrive au


diffuseur, il fait le tour de ses souscripteurs
et appelle la méthode de notification sur
leurs objets.

Analogie : abonnement aux magazines et aux journaux ;


recherche d’emploi, ...

49
Observer - Structure

1. Le Diffuseur envoie des événements intéressants à d’autres objets. Ces événements se produisent quand
le diffuseur change d’état ou exécute certains comportements. Le diffuseur possède une infrastructure
d’inscription qui permet aux nouveaux souscripteurs de rejoindre la liste et aux souscripteurs actuels de la
quitter.
50
Observer - Structure

2. Quand un nouvel événement survient, le diffuseur parcourt la liste d’inscriptions et appelle la méthode de
notification déclarée dans l’interface des souscripteurs sur chaque objet souscripteur.
3. L’interface Souscripteur déclare la méthode de notification update(). Elle peut prendre plusieurs paramètres
pour que le diffuseur leur envoie plus de détails concernant la modification.
51
Observer - Structure

4. Les Souscripteurs Concrets exécutent certaines actions en réponse aux notifications envoyées par le
diffuseur. Toutes ces classes doivent implémenter la même interface pour ne pas coupler le diffuseur avec leurs
classes concrètes.

52
Observer - Structure

5. En général, les souscripteurs ont besoin de détails à propos du contexte afin d’exécuter correctement la mise à
jour. C’est pour cela que les diffuseurs passent souvent des données du contexte en paramètre de la méthode de
notification.
6. Le Client crée des objets diffuseur et Souscripteur séparément et inscrit les souscripteurs aux mises à jour du
diffuseur. 53
Observer - Exemple avec l’éditeur de texte

54
Observer - Exemple avec l’éditeur de texte

55
Observer - Exemple avec l’éditeur de texte

56
Observer - Possibilités d’application

- Utilisez l'Observateur quand des modifications de l’état d’un objet peuvent en impacter
d’autres, et que l’ensemble des objets n’est pas connu à l’avance ou qu’il change
dynamiquement.

- Utilisez ce patron quand certains objets de votre application doivent en suivre d’autres,
mais seulement pendant un certain temps ou dans des cas spécifiques.

- Exercice : https://www.wooclap.com/EPIRIZ

57
Strategy

Objectif : Définir une famille d’algorithmes, et encapsuler chacun, et les rendre


interchangeables, tout en assurant que chaque algorithme puisse évoluer
indépendamment des clients qui l’utilisent.

58
Strategy

- La classe originale (le contexte) doit avoir un


attribut qui garde une référence vers une des
stratégies. Plutôt que de s’occuper de la tâche,
le contexte la délègue à l’objet stratégie
associé.
- Le contexte n’a pas la responsabilité de la
sélection de l’algorithme adapté, c’est le client
qui lui envoie la stratégie.
- Le contexte devient indépendant des stratégies
concrètes. Vous pouvez ainsi modifier des
algorithmes ou en ajouter de nouveaux sans
toucher au code du contexte ou aux autres
stratégies.

Raison d’utilisation : un objet doit pouvoir faire varier une partie de son algorithme dynamiquement.
Résultat : le patron stratégie permet d’isoler les algorithmes appartenant à une même famille d’algorithmes,
mais implique de créer beaucoup d’objets en mémoire 59
Strategy - Structure

1. Le Contexte garde une référence vers une des


stratégies concrètes et communique avec cet objet
uniquement au travers de l’interface stratégie.
2. L’interface Stratégie est commune à toutes les
stratégies concrètes. Elle déclare une méthode que
le contexte utilise pour exécuter une stratégie.
3. Les Stratégies Concrètes implémentent différentes
variantes d’algorithmes utilisées par le contexte.
4. Chaque fois qu’il veut lancer un algorithme, le
contexte appelle la méthode d’exécution de l’objet
stratégie associé. Le contexte ne sait pas comment
la stratégie fonctionne ni comment l’algorithme est
lancé.
5. Le Client crée un objet spécifique Stratégie et le
passe au contexte. Le contexte expose un setter
qui permet aux clients de remplacer la stratégie
associée au contexte lors de l’exécution.

60
Strategy - Exemple avec les opérations arithmétiques

61
Strategy - Exemple avec les opérations arithmétiques

62
Strategy - Possibilités d’application
- Utilisez le Stratégie si vous voulez avoir différentes variantes d’un algorithme à l’intérieur
d’un objet à disposition, et pouvoir passer d’un algorithme à l’autre lors de l’exécution.

- Utilisez la stratégie pour isoler la logique métier d’une classe, de l’implémentation des
algorithmes dont les détails ne sont pas forcément importants pour le contexte.

- Utilisez ce patron si votre classe possède un gros bloc conditionnel qui choisit entre
différentes variantes du même algorithme.

- Exercice : https://www.wooclap.com/EPIRIZ

63
Visitor

Visiteur vous permet de séparer les algorithmes et les objets sur lesquels ils
opèrent.

64
Visitor

- Le patron de conception visiteur vous propose de placer ce nouveau


comportement dans une classe séparée que l’on appelle visiteur, plutôt que de
l’intégrer dans des classes existantes.
- L’objet qui devait lancer ce traitement à l’origine est maintenant passé en
paramètre des méthodes du visiteur, ce qui permet à la méthode d’avoir accès à
toutes les données nécessaires qui se trouvent à l’intérieur de l’objet.

Comment fait-on pour que ce comportement puisse être exécuté sur des objets de différentes classes ?

65
Visitor
La classe visiteur va donc avoir besoin d’un ensemble de méthodes et chacune d’entre elles pourra prendre
des paramètres de différents types, comme ce qui suit :

Mais comment allons-nous appeler ces méthodes, surtout celles qui gèrent le graphe complet ?

66
Visitor
Le patron Visiteur utilise une technique appelée double répartition (double dispatch), qui aide à lancer la
bonne méthode sans s’encombrer avec des blocs conditionnels.

67
Visitor - Structure
1. L’interface Visiteur déclare un ensemble de méthodes de
parcours qui peuvent prendre les éléments concrets d’une
structure d’objets en paramètre. Ces méthodes peuvent
avoir le même nom si le programme est écrit dans un
langage qui gère la surcharge, mais le type de ses
paramètres sera différent.
2. Chaque Visiteur Concret implémente plusieurs versions
des mêmes comportements, en fonction des classes des
éléments concrets.
3. L’interface Élément déclare une méthode qui « accepte » les
visiteurs. Cette méthode déclare un paramètre du type de
l’interface visiteur.
4. Chaque Élément Concret doit implémenter une méthode
d’acceptation. Le but de cette méthode est de rediriger
l’appel vers la méthode appropriée du visiteur en fonction
de la classe de l’élément actuel.
5. Le Client représente en général une collection ou tout autre
objet complexe (par exemple un arbre Composite). En
général, les clients n’ont pas de visibilité sur les classes des
éléments concrets, car ils manipulent les objets de cette68
collection via une interface abstraite.
Visitor - Exemple avec l’export XML

69
Visitor - Exemple avec l’export XML

70
Visitor - Exemple avec l’export XML

71
Visitor - Exemple avec l’export XML

72
Visitor - Possibilités d’application

- Utilisez le visiteur lorsque vous voulez lancer des traitements sur les éléments d’un objet
ayant une structure complexe (une arborescence par exemple).

- Visiteur vous permet de lancer des traitements sur un ensemble d’objets de différentes
classes à l’aide d’un objet visiteur qui implémente une variante d’un même traitement pour
chaque classe visée.

- Utilisez le visiteur si un comportement n’est adapté que pour certaines classes d’une
hiérarchie de classes, mais pas pour les autres.

- Exercice : https://www.wooclap.com/EPIRIZ

73
23 Patrons GoF

74
https://slideplayer.com/slide/6667469/
Comparaison

- Vous pouvez utiliser le Visiteur pour lancer une opération sur un arbre
Composite entier.

75
Patrons POSA1

Exprime un schéma d'organisation Fournit un schéma pour affiner les


structurel fondamental pour un composants d'un système logiciel
système logiciel ou les relations entre eux.

Architecture Patterns Design Patterns

Layers Whole-Part

Pipes & Filters Master-Slave

Blackboard Proxy

Broker Command Processor

Model-View-Controller View handler

Presentation-Abstraction-Control Forwarded-Receiver

Microkernel Client-Dispatcher-Server
76
Reflection Publisher-Subscriber
● Layers

● Pipes & Filters

POSA1 ● Blackboard

● Broker
Patrons d’architecture
● Model-View-Controller
exprime un schéma d’organisation
structurel fondamental pour un système ● Presentation-Abstraction-Control

logiciel
● Microkernel

● Reflection

77
Model-View-Controller (MVC)

● Un modèle (Model) contient les données à


afficher.
● Une vue (View) contient la présentation de
l'interface graphique.
● Un contrôleur (Controller) contient la logique
concernant les actions effectuées par l'utilisateur
et coordonne les interactions entre la vue et le
modèle.

MVC a été mise au point en 1979 par Trygve Reenskaug,


qui travaillait alors sur Smalltalk dans les laboratoires de
recherche Xerox PARC
78
Model-View-Controller (MVC)

La vue correspond à l'interface avec laquelle l'utilisateur


interagit. Sa première tâche est de présenter les résultats
renvoyés par le modèle. Sa seconde tâche est de recevoir
toutes les actions de l'utilisateur (clic de souris, sélection
d'une entrée, boutons...). Ces différents événements sont
envoyés au contrôleur. La vue n'effectue aucun
traitement, elle se contente d'afficher les résultats des
traitements effectués par le modèle. Plusieurs vues,
partielles ou non, peuvent afficher des informations d'un
même modèle.

79
Model-View-Controller (MVC)

Le modèle représente le comportement de l'application :


traitements des données, interactions avec la base de
données, etc. Il décrit ou contient les données manipulées
par l'application. Il assure la gestion de ces données et
garantit leur intégrité. Dans le cas typique d'une base de
données, c'est le modèle qui la contient. Le modèle offre
des méthodes pour mettre à jour ces données (insertion,
suppression, changement de valeur). Il offre aussi des
méthodes pour récupérer ces données. Les résultats
renvoyés par le modèle sont dénués de toute présentation.

80
Model-View-Controller (MVC)

Le contrôleur prend en charge la gestion des événements


de synchronisation pour mettre à jour la vue ou le modèle
et les synchroniser. Il reçoit tous les événements de
l'utilisateur et enclenche les actions à effectuer. Si une
action nécessite un changement des données, le contrôleur
demande la modification des données au modèle et ensuite
avertit la vue que les données ont changé pour qu'elle se
mette à jour. Certains événements de l'utilisateur ne
concernent pas les données mais la vue. Dans ce cas, le
contrôleur demande à la vue de se modifier. Le contrôleur
n'effectue aucun traitement, ne modifie aucune donnée.
81
MVC : Observer est inclus

82
1. Single Responsibility Principle
2. Open/Closed Principle
Principes SOLID 3. Liskov Substitution Principle
4. Interface Segregation Principle
5. Dependency Inversion Principle

83
Single Responsibility Principle

Une classe ne devrait être modifiée que pour une seule raison.

Essayez de faire en sorte qu’une classe ne soit responsable que d’une partie
d’une fonctionnalité de votre logiciel, et encapsuler (vous pouvez aussi dire
cachez à l’intérieur) cette responsabilité entièrement dans la classe.

Objectif : diminuer la complexité

Si une classe s’occupe de trop de choses à la fois, vous devrez la modifier à la


moindre évolution -> provoquer des bugs.

Si vous éprouvez des difficultés à vous concentrer sur des aspects spécifiques
du programme, souvenez-vous de ce principe et vérifiez s’il est grand temps de
découper certaines classes en plusieurs parties.
84
Single Responsibility Principle - Example

85
Open/Closed Principle

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


(sauf s’il y a un bug).

L’idée est d’éviter de créer des bugs dans du code existant lorsque vous ajoutez de
nouvelles fonctionnalités.

Une classe est ouverte si vous pouvez l’étendre, créer une sous-classe ou faire
n’importe quoi d’autre avec ; Une classe est fermée si elle est prête à 100 % à être
utilisée par d’autres classes (son interface est clairement définie et ne sera plus
modifiée dans le futur).

86
Open/Closed Principle - Example

87
Open/Closed Principle - Example

Stratégie

En concordance avec le principe


de responsabilité unique, cette
solution vous permet de déplacer
le calcul du délai de livraison dans
des classes plus pertinentes.

88
Liskov Substitution Principle

Lorsque vous étendez une classe, rappelez-vous que vous devez être en mesure de
passer des objets de la sous-classe à la place des objets de la classe mère sans
faire planter le code.

Cela signifie que les sous-classes restent compatibles avec le comportement de la


classe mère. Lorsque vous redéfinissez une méthode, étendez le comportement de
base plutôt que de le remplacer complètement avec autre chose.

89
Liskov Substitution Principle : prérequis des sous-classes

● Les types des paramètres de la méthode d’une sous-classe doivent


correspondre ou être plus abstraits que les types des paramètres dans la
méthode de la classe mère :
○ classe mère : nourrir(Chat c)
○ sous-classe : nourrir(Animal c) ? ou nourrir(ChatBengal c) ?
● Le type de retour dans une méthode d’une sous-classe doit correspondre ou
être un sous-type du type de retour de la méthode de la classe mère :
○ classe mère : acheterChat(): Chat
○ sous-classe : acheterChat(): ChatBengal ? ou acheterChat(): Animal ?
● Une méthode dans une sous-classe ne devrait pas lever les types d’exceptions
que la méthode de base n’est pas censée lever.

90
Liskov Substitution Principle : prérequis des sous-classes

● Une sous-classe ne devrait pas renforcer des préconditions.


○ classe mère : int somme(int nbre1, int nbre2)
○ sous-classe : int somme(int nbre1, int nbre2) à condition que nbre1 et nbre2 soient positives (en
levant une exception si la valeur est négative)
● Une sous-classe ne devrait pas affaiblir des postconditions.
○ classe mère : une méthode pour connecter à une bdd. Cette méthode est censée toujours fermer
les connexions ouvertes à la bdd lorsqu’elle renvoie une valeur.
○ sous-classe : laisser les connexions ouvertes, alors que le client s’attend à ce que toutes les
méthodes ferment les connexions, alors il pourrait très bien décider de fermer le programme
juste après avoir appelé la méthode, polluant le système avec une connexion fantôme à la base
de données.
● Les invariants d’une classe mère doivent être préservés.
● Une sous-classe ne doit jamais modifier les valeurs des attributs privés d’une
classe mère.
91
Liskov Substitution Principle - Exemple

La méthode de la sous-classe
DocumentEnLectureSeule lève une exception
si elle est appelée. La méthode de base ne
possède pas cette restriction.

92
Liskov Substitution Principle - Exemple

Une sous-classe peut étendre le


comportement d’une classe mère. Le
document en lecture seule devient donc la
classe de base de la hiérarchie. Le document
ouvert en écriture est maintenant une
sous-classe qui étend la classe de base et
ajoute le comportement de sauvegarde.

93
Interface Segregation Principle

Les clients ne devraient pas être forcés à dépendre de méthodes qu’ils n’utilisent pas.

Essayez de rendre vos interfaces aussi étroites que possible afin de ne pas obliger les
classes des clients à implémenter des comportements dont elles n’ont pas besoin ->
découper vos « grosses » interfaces pour les rendre plus précises et spécifiques.

Les clients ne doivent implémenter que les méthodes dont ils ont vraiment besoin.
Sinon, une modification apportée dans une « grosse » interface va même faire planter
les clients qui n’utilisent pas les méthodes modifiées.

94
Interface Segregation Principle - Exemple

Gardez un certain équilibre.


95
Dependency Inversion Principle

Les classes de haut niveau ne devraient pas dépendre des classes de bas niveau. Elles
devraient dépendre toutes les deux d’abstractions. Une abstraction ne doit pas
dépendre des détails. Les détails doivent dépendre de l’abstraction.

Les classes de bas niveau implémentent des traitements basiques comme utiliser le
disque, transférer des données sur un réseau, se connecter à une base de données, etc.

Les classes de haut niveau contiennent la logique métier qui indique aux classes de
bas niveau ce qu’elles doivent faire.

Le principe d’inversion des dépendances est souvent utilisé en corrélation avec le


principe ouvert/fermé : vous pouvez étendre les classes de bas niveau pour utiliser
différentes classes de la logique métier sans avoir à modifier les classes existantes.
96
Dependency Inversion Principle

1. Pour commencer, vous devez décrire les interfaces pour les traitements de bas
niveau dont les classes de haut niveau vont avoir besoin, de préférence en utilisant
les termes de la logique métier.
a. Par exemple, la logique métier doit appeler une méthode ouvrirRapport(fichier) plutôt qu’une suite de
méthodes ouvrirFichier(x) , lireOctets(n) ,fermerFichier(x) . Ces interfaces font partie du haut niveau.
2. Maintenant, vous pouvez rendre les classes de haut niveau dépendantes de ces
interfaces, plutôt que de les rendre dépendantes des classes concrètes de bas
niveau. Cette dépendance sera bien plus faible que celle d’origine.
3. Une fois que les classes de bas niveau implémentent ces interfaces, elles
deviennent dépendantes de la logique métier, inversant la direction de la
dépendance originale.

97
Dependency Inversion Principle - Exemple

98
Références

1. https://refactoring.guru/fr/design-patterns
2. https://springframework.guru/gang-of-four-design-patterns/
3. http://fr.slideshare.net/mohamedyoussfi9
4. http://www.newthinktank.com/videos/design-patterns-tutorial/
5. Alexander Shvets. “Plongée au cœur des patrons de conception.”, v2021-1.6.

99

Vous aimerez peut-être aussi