SlideShare une entreprise Scribd logo
1  sur  147
Télécharger pour lire hors ligne
Design Patterns
En C#
Qui suis-je ?
• Dorra BARTAGUIZ
• Software craftswoman
• Tech lead
• Coach technique
• Peu importe le langage
• .Net, java, php, python, js
dorra.bartaguiz@outlook.com
Programme
Du code C# à faire/factoriser Contexte
Problématique
Extraire le
design pattern
Des questions ?
C’est parti 
Design pattern - Définition
• Modèle de conception
• Décrit les cas d’utilisation
• Sert d’abstraction au modèle d’implémentation
• Intension, motivation, solution
• Une solution à un problème générique
Premier exemple
• Projet à récupérer de GitHub
• https://github.com/iAmDorra/DesignPatterns
Folder
+ Name : String
File
+ Name : String
contains
contains
Solution & Projet
• Définir le projet (ou les) de
démarrage
• Références d’un projet
• Un autre projet
• Une librairie du Framework
• Un composant COM
• …
Project 1
Project 2
References
Solution
Project 3
References
Project 4
2
1
1'
3
References
x Build order
Premier exemple
• Contexte :
• Un dossier peut contenir des fichiers et des dossiers
Folder
+ Name : String
File
+ Name : String
contains
contains
Premier exemple
• Inconvénients :
• Pour connaitre le contenu de Folder, il faut parcourir les deux listes
Folder
+ Name : String
File
+ Name : String
contains
contains
Premier exemple
• Pour connaitre le contenu de Folder, il faut parcourir une seule
collection
Folder
+ Name : String
File
+ Name : String
<<Interface>>
IElement
+ Name : String
Premier exemple
• Caractéristiques
• Eviter la duplication
• Extensible
=> Pattern « Composite »
Folder
+ Name : String
File
+ Name : String
contains
contains
Folder
+ Name : String
File
+ Name : String
<<Interface>>
IElement
+ Name : String
Exercice
• Ajouter un lien (Link)
• Un lien peut référencer un fichier ou un dossier (pas les deux)
• Un dossier peut contenir des liens
Folder
+ Name : String
File
+ Name : String
<<Interface>>
IElement
+ Name : String
Petits rappels avant

SOLID
• S RP : Single Responsibility Principle
• O CP : Open Close Principle
• L SP : Liskov Substitution Principle
• I SP : Interface Separation Principle
• D IP : Dependency Inversion Principle
Classification des patterns
• GoF (Gang of four) classification
• Creational patterns (de construction)
• Behavior patterns (de comportement)
• Structural patterns (de structuration)
Revenons à nos moutons

Composite
• Permettre à un client d’interagir avec un objet sans connaitre la
profondeur de sa composition
• Limiter les dépendances entre les classes concrètes
• Eviter la duplication
• Extensible
Folder
+ Name : String
File
+ Name : String
<<Interface>>
IElement
+ Name : String
Composite – use cases
• Il est nécessaire de représenter des hiérarchies de composition
• Les clients de la composition doivent ignorer s’ils communiquent avec
des objets composés ou non
Folder
+ Name : String
File
+ Name : String
<<Interface>>
IElement
+ Name : String
Use Case

Le système solaire
• Il est composé de :
• Le soleil
• Des planètes
• Autres étoiles et objets célestes
Le système solaire
Sun
- instance : Sun
+ GetInstance() : Sun
private static Sun instance = new Sun();
private Sun()
{
}
public static Sun GetInstance()
{
return instance;
}
Singleton
• Assurer qu’une classe ne possède qu’une seule instance et de fournir
une méthode de classe unique retournant cette instance
Singleton
- instance : Singleton
+ GetInstance() : Singleton
private static Singleton instance = new Singleton();
private Singleton()
{
}
public static Singleton GetInstance()
{
return instance;
}
Singleton – use cases
• Il ne doit y avoir qu’une seule instance
• Cette instance n’est accessible qu’à travers une méthode de classe
• Eviter une variable globale
Singleton
- instance : Singleton
+ GetInstance() : Singleton
private static Singleton instance = new Singleton();
private Singleton()
{
}
public static Singleton GetInstance()
{
return instance;
}
Singleton – use cases
On peut avoir une version lazy du singleton
Singleton
- instance : Singleton
+ GetInstance() : Singleton
private static Singleton instance;
public static Singleton GetInstance()
{
if(instance == null)
instance = new Singleton();
return instance
}
Singleton – attention
• Si on est en multithreading, ajout un lock pour l’instance
• Eviter les méthodes qui set l’instance à null
Singleton
- instance : Singleton
+ GetInstance() : Singleton
+ Reset()
public static Singleton GetInstance()
{
if(instance == null)
instance = new Singleton();
return instance
}
public void Reset()
{
instance = null;
}
var first = Singleton.GetInstance();
// first pointe donc sur un objet en mémoire
first .Reset();
var second = Singleton.GetInstance();
// => on a donc deux instances en mémoire
Use Case

Appel au service client
• Un client achète un article sur un site et paye par carte bancaire
• Il veut changer l’adresse de livraison et rajouter une option dans
l’article
• Le changement d’adresse est au service de facturation
• L’ajout de l’option est au service de commande
• Il appelle le service client qui se charge de tout
Appel au service client
CustomerService
+ UpdateAdress(Client client, Adress
newAdress)
+ AddOption(Order order, Option option)
Billing
+ AddOption(Order order, Option option)
+ Edit(Order order)
Ordering
+UpdateAdress(Client client, Adress
newAdress)
Uses
public void UpdateAdress(Client client, Adress newAdress)
{
ordering.UpdateAdress(client, newAdress);
}
public void AddOption(Order order, Option option)
{
billing.AddOption(order, option);
}
Façade
• Créer une interface unifiée au sous-système
• Un objet composé de plusieurs services
Facade
+ RunMethod1(parameter1, parameter2)
+ RunMethod3()
+ RunMethod4(parameter3)
Service3
+ RunMethod4(parameter3)
+ RunMethod5(parameter)
Service2
+ RunMethod3()
Service1
+ RunMethod1(parameter1, parameter2)
+ RunMethod2()
Façade – use cases
• Dissimuler/faciliter au client la complexité des activités internes
• Besoin de contrôler les modes d’accès aux composants
• Un point d’entrée au sous-système Facade
+ RunMethod1(parameter1, parameter2)
+ RunMethod3()
+ RunMethod4(parameter3)
Service3
+ RunMethod4(parameter3)
+ RunMethod5(parameter)
Service2
+ RunMethod3()
Service1
+ RunMethod1(parameter1, parameter2)
+ RunMethod2()
Façade – attention
• Fort couplage
• Degré de dépendance d’un module vis-à-
vis d’un autre
• Faible cohésion
• Degré de cohérence des responsabilités
d’un module
Facade
+ RunMethod1(parameter1, parameter2)
+ RunMethod3()
+ RunMethod4(parameter3)
Service3
+ RunMethod4(parameter3)
+ RunMethod5(parameter)
Service2
+ RunMethod3()
Service1
+ RunMethod1(parameter1, parameter2)
+ RunMethod2()
Use Case

Compresser des données
• On a besoin de compresser des données
• Codage par répétition
• AAA0000111FF => 3A40312F
• Codage entropique (de Huffman ou arithmétique)
• Pattern => 000 001 11 11 010 011 10
Compresser des données
Compressor
+ string Compress(string data)
<<Interface>>
ICompressor
+ string Compress(string data)
public string Compress(string data)
{
switch (this.compressionType)
{
case CompressionType.Repetition:
return CompressWithRepetitionAlgo(data);
case CompressionType.Entropic:
return CompressWithEntropicAlgo(data);
case CompressionType.ByDictionary:
return CompressByDictionaryAlgo(data);
default:
return data;
}
}
Compresser des données
RepetitionCompressor
+ string Compress(string data)
<<Interface>>
ICompressor
+ string Compress(string data)
EntropicCompressor
+ string Compress(string data)
Context
- compressor : ICompressor
+ string Compress(string data)
ByDictionaryCompressor
+ string Compress(string data)
public string Compress(string data)
{
compressor.Compress(data);
}
Strategy
• Adapter le comportement d’un objet en fonction d’un besoin sans
changer les interactions de cet objet avec les clients
• Représenter les comportements variables sous forme de classes
• Les comportements/algorithmes sont interchangeables
ConcreteStrategyA
+ Calculate()
<<Interface>>
Strategy
+ Calculate()
ConcreteStrategyB
+ Calculate()
Context
+ Execute()
void Execute()
{
strategy.Calculate();
}
Strategy – use cases
• Besoin d’implémenter plusieurs comportements pour un traitement
• Protéger les variations en séparant les parties variantes et invariantes
ConcreteStrategyA
+ Calculate()
<<Interface>>
Strategy
+ Calculate()
ConcreteStrategyB
+ Calculate()
Context
+ Execute()
void Execute()
{
strategy.Calculate();
}
Strategy – attention
• Quand les contextes sont responsables du choix de la stratégie
ConcreteStrategyA
+ Calculate()
<<Interface>>
Strategy
+ Calculate()
ConcreteStrategyB
+ Calculate()
Context
+ Execute()
void Execute()
{
strategy.Calculate();
}
Use Case

Chez le concessionnaire
• Le concessionnaire gère les commandes issues de client de la France
et du Luxembourg.
• La différence entre les commandes concerne le calcul de la TVA
• France : TVA = 19,6%
• Luxembourg : TVA = 12% pour les prestations et 15% pour le matériel
Chez le concessionnaire
• Montant = HT + TVA
<<Interface>>
IOrder
+CalculateAmount()
FrenchOrder
-preTaxAmount
+CalculateAmount()
LuxembourgishOrder
-preTaxServiceAmount
-preTaxMaterialAmount
+CalculateAmount()
public double CalculateAmount()
{
var vatAmount = preTaxAmount * 0.196;
var amount = preTaxAmount + vatAmount;
return amount;
}
public double CalculateAmount()
{
var vatAmount = preTaxServiceAmount * 0.12 +
preTaxMaterialAmount * 0.15;
var preTaxAmount = preTaxServiceAmount +
preTaxMaterialAmount;
var amount = preTaxAmount +
vatAmount;
return amount;
}
Chez le concessionnaire
• Montant = HT + TVA
• Extraire les méthodes
• Mieux voir les factorisations
futures
<<Interface>>
IOrder
+CalculateAmount()
FrenchOrder
-preTaxAmount
+CalculateAmount()
LuxembourgishOrder
-preTaxServiceAmount
-preTaxMaterialAmount
+CalculateAmount()
public double CalculateAmount()
{
var amount = CalculatePreTaxAmount()+
CalculateVat();
return amount;
}
private double CalculateVat()
{
return preTaxAmount * 0.196;
}
private double CalculatePreTaxAmount()
{
return preTaxAmount;
}
public double CalculateAmount()
{
var amount = CalculatePreTaxAmount()+
CalculateVat();
return amount;
}
private double CalculateVat()
{
return preTaxServiceAmount * 0.12 +
preTaxMaterialAmount * 0.15;
}
private double CalculatePreTaxAmount()
{
return preTaxServiceAmount +
preTaxMaterialAmount;
}
Chez le concessionnaire
• Montant = HT + TVA
• Factoriser le comportement
dans la classe de base
• Implémenter les spécificités
dans les classes filles
<<Interface>>
IOrder
+CalculateAmount()
FrenchOrder
-preTaxAmount
#CalculateVat()
#CalculatePreTaxAmount()
LuxembourgishOrder
-preTaxServiceAmount
-preTaxMaterialAmount
#CalculateVat()
#CalculatePreTaxAmount()
<<Abstract>>
BaseOrder
+CalculateAmount()
#CalculateVat()
#CalculatePreTaxAmount()
protected override double CalculateVat()
{
return preTaxAmount * 0.196;
}
protected override double CalculatePreTaxAmount()
{
return preTaxAmount;
}
protected override double CalculateVat()
{
return preTaxServiceAmount * 0.12 +
preTaxMaterialAmount * 0.15;
}
protected override double CalculatePreTaxAmount()
{
return preTaxServiceAmount +
preTaxMaterialAmount;
}
public double CalculateAmount()
{
return CalculateVat() + CalculatePreTaxAmount();
}
protected abstract double CalculateVat();
protected abstract double CalculatePreTaxAmount();
Template method
• Reporter aux filles
certaines étapes d’un
traitement
• Les étapes sont
implémentées dans
les classes filles
ConcreteClass
#Operation1()
#Operation2()
<<Abstract>>
BaseClass
+TemplateMethod()
#Operation1()
#Operation2()
public void TemplateMethod()
{
...
Operation1();
...
Operation2();
...
}
protected abstract void Operation1();
protected abstract void Operation2();
protected override void Operation1()
{
...
}
protected override void Operation2()
{
...
}
Template method – use cases
• Deux classes ou plusieurs
partagent du code
identique
• Les parties spécifiques
déplacées dans les filles
• Un algorithme avec une
partie invariable et des
parties spécifiques à
différents objets ConcreteClass
#Operation1()
#Operation2()
<<Abstract>>
BaseClass
+TemplateMethod()
#Operation1()
#Operation2()
public void TemplateMethod()
{
...
Operation1();
...
Operation2();
...
}
protected abstract void Operation1();
protected abstract void Operation2();
protected override void Operation1()
{
...
}
protected override void Operation2()
{
...
}
Use Case

L’usine à chaussures
• L’usine crée
• Des chaussures de ville, des sandales
• En cuir ou synthétiques
ShoeCreator
+ CreateLeatherShoe()
+ CreateLeatherSandal()
+ CreateSyntheticShoe()
+ CreateSyntheticSandal()
IShoe
-type
Client
Sandal
-type
StreetShoe
-type
public StreetShoe CreateLeatherShoe()
{
return new StreetShoe(ShoeType.Leather);
}
public Sandal CreateSyntheticSandal()
{
return new Sandal(ShoeType.Synthetic);
}
L’usine à chaussures
ShoeCreator
+ CreateShoe()
+ CreateSandal()
IShoe
Client
Sandal
StreetShoe
LeatherFabric
+ CreateShoe()
+ CreateSandal()
SyntheticFabric
+ CreateShoe()
+ CreateSandal()
LeatherSandal SyntheticSandal
LeatherStreetShoe SyntheticStreetShoe
public StreetShoe CreateShoe()
{
return new LeatherStreetShoe();
}
public Sandal CreateSandal()
{
return new LeatherSandal();
}
public StreetShoe CreateShoe()
{
return new SyntheticStreetShoe();
}
public Sandal CreateSandal()
{
return new SyntheticSandal();
}
Abstract factory
• Créer des objets regroupés
en familles sans devoir
connaître les classes
concrètes destinées à la
création de ces objets
• Configuration flexible
• Les implémentations
doivent changer en fonction
de certains paramètres
AbstractFabric
+ CreateProductA()
+ CreateProductB()
Client
ProductA
ProductB
ConcreteFabric1
+ CreateProductA()
+ CreateProductB()
ConcreteFabric2
+ CreateProductA()
+ CreateProductB()
ProductA1 ProductA2
ProductB1 ProductB2
Abstract factory – use cases
• Un système utilisant des
produits a besoin d’être
indépendant de la façon
dont ces produits sont créés
et regroupés
• Un système est paramétré
par plusieurs familles de
produits qui peuvent
évoluer
AbstractFabric
+ CreateProductA()
+ CreateProductB()
Client
ProductA
ProductB
ConcreteFabric1
+ CreateProductA()
+ CreateProductB()
ConcreteFabric2
+ CreateProductA()
+ CreateProductB()
ProductA1 ProductA2
ProductB1 ProductB2
Abstract factory - attention
• Si une règle de gestion
exige de ne pas pouvoir
créer des sandales en
synthétique par exemple,
ce pattern ne correspond
pas car on va implémenter
la méthode CreateSandal
pour le synthétique
• Risque de créer des objets
incompatibles entre eux
AbstractFabric
+ CreateProductA()
+ CreateProductB()
Client
ProductA
ProductB
ConcreteFabric1
+ CreateProductA()
+ CreateProductB()
ConcreteFabric2
+ CreateProductA()
+ CreateProductB()
ProductA1 ProductA2
ProductB1 ProductB2
Use Case

Faire du shopping
• Un client commande des articles sur internet
• Statuts de la commande :
• En cours : le client est en train de choisir les articles
• Validée : le client valide et paye la commande
• Livrée : le client reçoit les articles
Faire du shopping
• Inconvénients
• Il faut gérer tous les statuts
dans les méthodes
• Les transitions des statuts
sont gérées par la
commande
Order
- state
- items
+ AddItem()
+ RemoveItem()
+ NextState()
public void AddItem(Item item)
{
if(state == InProgress)
{
items.Add(item);
}
else
{
throw new System.NotSupportedException();
}
}
public void RemoveItem(Item item)
{
if(state == InProgress || state == Validated)
{
items.Remove(item);
}
else
{
throw new System.NotSupportedException();
}
}
Faire du shopping
• Inconvénients
• Il faut gérer tous les statuts
dans les méthodes
• Les transitions des statuts
sont gérées par la
commande
• Nouvel objet à
chaque modif de
statut
Order
-state
-items
+AddItem()
+RemoveItem()
+NextState()
InprogressOrder
+AddItem()
+RemoveItem()
ValidatedOrder
+AddItem()
+RemoveItem()
DeliveredOrder
+AddItem()
+RemoveItem()
public void AddItem(Item item)
{
throw new NotSupportedException();
}
public void RemoveItem(Item item)
{
throw new NotSupportedException();
}
public void AddItem(Item item)
{
throw new NotSupportedException();
}
public void RemoveItem(Item item)
{
items.Remove(item);
}
public void AddItem(Item item)
{
items.Add(item);
}
public void RemoveItem(Item item)
{
items.Remove(item);
}
Faire du shopping
• Inconvénients
• Il faut gérer tous les statuts
dans les méthodes
• Les transitions des statuts
sont gérées par la
commande
• Nouvel objet à
chaque modif de
statut
OrderStatus
+AddItem()
+RemoveItem()
InprogressStatus
+AddItem()
+RemoveItem()
ValidatedStatus
+AddItem()
+RemoveItem()
DeliveredStatus
+AddItem()
+RemoveItem()
Order
-state
-items
+AddItem()
+RemoveItem()
+NextState()
public void AddItem(Item item)
{
throw new NotSupportedException();
}
public void RemoveItem(Item item)
{
throw new NotSupportedException();
}
public void AddItem(Item item)
{
throw new NotSupportedException();
}
public void RemoveItem(Item item)
{
items.Remove(item);
}
public void AddItem(Item item)
{
items.Add(item);
}
public void RemoveItem(Item item)
{
items.Remove(item);
}
public void AddItem(Item item)
{
state.AddItem(item);
}
public void RemoveItem(Item item)
{
state.RemoveItem(item);
}
State
• Permet à un objet (Context) d’adapter son comportement en fonction
de son état interne
Context
+Request()
State
+Handle()
ConcreteStateA
+Handle()
ConcreteStateB
+Handle()
Request()
{
state.Handle();
}
State – use cases
• Le comportement d’un objet dépend de son état
• L’implémentation par des instructions conditionnelles est trop complexe
Context
+Request()
State
+Handle()
ConcreteStateA
+Handle()
ConcreteStateB
+Handle()
Request()
{
state.Handle();
}
State – attention
• Ne pas implémenter si deux états (simples)
Context
+Request()
State
+Handle()
ConcreteStateA
+Handle()
ConcreteStateB
+Handle()
Request()
{
state.Handle();
}
Use Case

Comparateur d'hôtels
• J’ai créé un service de comparaison des hôtels du coin
• Je veux cherche des clients potentiels pour mon service
Comparator
+ GetAvailableRooms(Date) : List<RoomPrice>
<<Interface>>
IComparator
+ GetAvailableRooms(Date) : List<RoomPrice>
Comparator
+ GetAvailableRooms(Date) : List<RoomPrice>
Client
<<Interface>>
IComparator
+ GetRoomAvailailities(Date) : List<RoomAvailability>
<<Interface>>
IComparator
+ GetAvailableRooms(Date) : List<RoomPrice>
Comparateur d'hôtels
• Le client impose un contrat de service qui lui correspond
?
Comparateur d'hôtels
• Le client impose un contrat de service qui lui correspond
Comparator
+ GetAvailableRooms(Date) : List<RoomPrice>
Client
<<Interface>>
IComparator
+ GetRoomAvailailities(Date) : List<RoomAvailability>
<<Interface>>
IComparator
+ GetAvailableRooms(Date) : List<RoomPrice>
ComparatorAdaptor
+ GetRoomAvailailities(Date) : List<RoomAvailability>
Adapter
• Convertir une class existante en une interface attendue par les clients
également existants afin qu’ils puissant travailler ensemble
Adaptee
+ SpecificRequest()
Client
<<Interface>>
ITarget
+ Request()
Adapter
+ Request()
adaptee.SpecificRequest()
Adapter – use cases
• Intégrer dans un système un objet dont l’interface ne correspond pas à
l’interface requise au sein de ce système
• Fournir des interfaces multiples à un objet lors de sa conception
Adaptee
+ SpecificRequest()
Client
<<Interface>>
ITarget
+ Request()
Adapter
+ Request()
adaptee.SpecificRequest()
Adapter – attention
• Il y aura autant d’adaptateurs que de fournisseur
Adaptee
+ SpecificRequest()
Client
<<Interface>>
ITarget
+ Request()
Adapter
+ Request()
adaptee.SpecificRequest()
Use Case

Compter le nombre de LIKE
• Dans mon application, j’ai un service pour liker mon produit
• Créer un service de comptage
LikeCounter
+ CountLikes()
ProductAnalysis
+ LikeProduct()
Compter le nombre de LIKE
LikeCounter
+ Update(int)
<<Interface>>
ILikeCounter
+ Update(int)
ProductAnalysis
- List<ILikeCounter> counters
+ Add(ILikeCounter)
+ LikeProduct()
public void Add(ILikeCounter counter)
{
counters.Add(counter);
}
public void LikeProduct()
{
likesNumber ++;
foreach(var counter in this.counters)
{
counter.Update(likesNumber);
}
}
public LikeCounter(ProductAnalysis product)
{
product.Add(this);
}
public void Update(int number)
{
Console.WriteLine(number);
}
Observer
• Permet aux observateurs de mettre à jour leur état quand le sujet est
modifié
<<abstract>>
Subject
+ Add(Observer)
+ Remove(Observer)
+ Notify()
ConcretSubject
- subjectState
+ GetState()
<<abstract>>
Observer
+ Update()
ConcreteObserver
- observerState
+ Update()
subject
observer
return subjectState;
public void Add(Observer observer)
{
this.observers.Add(observer);
}
public void Notify()
{
foreach(var obs in observers)
{
obs.Update();
}
}
public void Update()
{
observerState = subject.GetState();
}
Observer – use cases
• La modification d’un objet engendre des modifications dans d’autres
objets qui sont déterminés dynamiquement
• Un objet veut prévenir d’autres objets sans devoir connaitre leur type
• pas de couplage
<<abstract>>
Subject
+ Add(Observer)
+ Remove(Observer)
+ Notify()
ConcretSubject
- subjectState
+ GetState()
<<abstract>>
Observer
+ Update()
ConcreteObserver
- observerState
+ Update()
subject
observer
return subjectState;
public void Add(Observer observer)
{
this.observers.Add(observer);
}
public void Notify()
{
foreach(var obs in observers)
{
obs.Update();
}
}
public void Update()
{
observerState = subject.GetState();
}
Observer – Attention
• Plusieurs implémentations
• Garder le statut dans le sujet et l’appeler dans la méthode Update de l’observer
• Ne pas exposer le statut du sujet et envoyer Event (contient les infos de
notification)
<<abstract>>
Subject
+ Add(Observer)
+ Remove(Observer)
+ Notify(Event)
<<abstract>>
Observer
+ Update(Event)
ConcreteObserver
- observerState
+ Update(Event)
observer
public void Add(Observer observer)
{
this.observers.Add(observer);
}
public void Notify(Event e)
{
foreach(var obs in observers)
{
obs.Update(e);
}
}
public void Update(Event e)
{
observerState = e;
}
Use Case

Composer son PC
• Choisir les options
• Taille écran : 11’, 16’ …
• Processeur : i5, i7 …
• Mémoire RAM : 12 Go, 16 Go …
• Taille du disque dur : 1To, SSD …
• Carte vidéo : NVIDIA, AMD …
• Casque : USB, Bluetooth …
• Souris : filaire, sans fil…
• Sac : à dos, sacoche …
• Clavier : Azerty, Querty
• Chaque option a un prix
• Le prix du PC = prix de base
(300€) + somme des options
Use Case

Chez le dentiste
• L’assistante accueille les patients par ordre d’arrivée
• Le dentiste ne sait pas s’il y a un patient qui attend, ni qui il est
• Il demande de faire entrer le suivant
• Il ne s’intéresse pas à la façon dont la salle d’attente est gérée.
Dentist
+ EnterNext()
Patient
- name
works with
Secretary
- patients : Collection<Patient>
+ HasNext() : bool
+ Next() : Patient
Chez le dentiste
• Introduire la notion de collection pour dissocier la collection en tant
que tel et la manière de la parcourir
• Si on change la règle d’itération par arrivée en itération par priorité
Dentist
+ EnterNext()
Patient
- name
works with
Secretary
+ HasNext() : bool
+ Next() : Patient
Patients
+
Chez le dentiste
Dentist
+ EnterNext()
Secretary
+ HasNext() : bool
+ Next() : Patient
Patients
+ GetIterator() : IIterator
<<Interface>>
IIterable
+ GetIterator() : IIterator
<<Interface>>
IIterator
+ HasNext() : bool
+ Next() : IElement
implements
<<Interface>>
IElement
Name
Patient
Name
instanciate
IIterator GetIterator()
{
return new Secretary();
}
void EnterNext()
{
IIterator iterator = this.patients.GetIterator();
if(iterator.HasNext())
{
this.Receive(iterator.Next());
}
}
Iterator
• Fournir un accès séquentiel à une collection à des
clients sans que ceux-ci doivent se préoccuper de
l’implémentation de cette collection
• Parcours séquentiel / variable
• Enumération Client
+ DoSomething()
ConcreteIterator<Element>
+ HasNext() : bool
+ Next() : Element
ConcreteIterable
+ GetIterator() : IIterator<IElement>
<<Interface>>
IIterable
+ GetIterator() : IIterator<IElement>
<<Interface>>
IIterator<IElement>
+ HasNext() : bool
+ Next() : IElement
implements
<<Interface>>
IElement
Element
instanciate
void DoSomething()
{
IIterator<IElement> iterator = this.iterable.GetIterator();
if(iterator.HasNext())
{
this.Receive(iterator.Next());
}
}
Iterator – use cases
• Parcours du contenu d’une collection sans accéder à sa représentation
interne
• Gérer plusieurs parcours simultanément
Client
+ DoSomething()
ConcreteIterator<Element>
+ HasNext() : bool
+ Next() : Element
ConcreteIterable
+ GetIterator() : IIterator<IElement>
<<Interface>>
IIterable
+ GetIterator() : IIterator<IElement>
<<Interface>>
IIterator<IElement>
+ HasNext() : bool
+ Next() : IElement
implements
<<Interface>>
IElement
Element
instanciate
void DoSomething()
{
IIterator<IElement> iterator = this.iterable.GetIterator();
if(iterator.HasNext())
{
this.Receive(iterator.Next());
}
}
Iterator – Attention
• L’ordre n’est pas maitrisé par le client mais plutôt par l’itérateur
Client
+ DoSomething()
ConcreteIterator<Element>
+ HasNext() : bool
+ Next() : Element
ConcreteIterable
+ GetIterator() : IIterator<IElement>
<<Interface>>
IIterable
+ GetIterator() : IIterator<IElement>
<<Interface>>
IIterator<IElement>
+ HasNext() : bool
+ Next() : IElement
implements
<<Interface>>
IElement
Element
instanciate
void DoSomething()
{
IIterator<IElement> iterator = this.iterable.GetIterator();
if(iterator.HasNext())
{
this.Receive(iterator.Next());
}
}
Use Case

Catalogue de films
• Au lieu de charger tout le film en mémoire, on affiche une image
• Un clic sur la photo permet de jouer le film
• But : réduire la quantité de mémoire utilisée
Catalogue de films
• Au lieu de charger tout le
film en mémoire, on
affiche une image
• Un clic sur la photo permet
de jouer le film
• But : réduire la quantité de
mémoire utilisée
Animation
+ Show()
+ Clic()
Film
+ Show()
+ Clic()
+ Run()
AnimationSubstitute
# photo
+ Show()
+ Clic()
0..1
#film
public void Show()
{
if(film == null)
photo.Show();
else
film.Show();
}
public void Clic()
{
if(film == null)
{
film = new Film();
}
film.Run();
}
Proxy
• Concevoir un objet qui se substitue à un autre et qui en contrôle
l’accès
<<Interface>>
ISubject
+ DoSomething()
RealSubject
+ DoSomething()
Proxy
- wrapee
+ DoSomething()
Client
public void DoSomething()
{
// Optionnal functionnality
wrapee.DoSomething();
// Optionnal functionnality
}
Proxy – use cases
• Proxy virtuel : créer un objet de taille importante au moment approprié
• Proxy remote : accéder à un objet s’exécutant sur un autre environnement
• Proxy de protection : sécuriser l’accès à un objet (authentification)
<<Interface>>
ISubject
+ DoSomething()
RealSubject
+ DoSomething()
Proxy
- wrapee
+ DoSomething()
Client
public void DoSomething()
{
// Optionnal functionnality
wrapee.DoSomething();
// Optionnal functionnality
}
Use Case

Chez le grossiste de fournitures bureau
• Tous les mois, l’école passe la même commande de fournitures (stylo,
feutres, papiers …)
• Afin de faciliter la saisie pour ses clients, le grossiste a décidé de
fournir une fonctionnalité de duplication de commande passée
Chez le grossiste de fournitures bureau
• Fonctionnalité de duplication de commande
<<Interface>>
ICloneableOrder
+ Clone()
Order
+ Clone()
Client
+ CreateOrderFromAnother()
order
public void CreateOrderFromAnother()
{
...
var newOrder = order.Clone();
...
}
public ICloneableOrder Clone()
{
return this.MemberwiseClone();
}
Prototype
• Créer de nouveaux objets par duplication d’objets existants qui
disposent de la capacité de clonage
<<Interface>>
IPrototype
+ Clone()
ContretePrototype1
+ Clone()
ContretePrototype2
+ Clone()
Client
+ Operation()
prototype
public void Operation()
{
...
var clone = prototype.Clone();
...
}
public IPrototype Clone()
{
return this.MemberwiseClone();
}
Prototype – uses cases
• Créer des instances sans connaitre la hiérarchie des classes
<<Interface>>
IPrototype
+ Clone()
ContretePrototype1
+ Clone()
ContretePrototype2
+ Clone()
Client
+ Operation()
prototype
public void Operation()
{
...
var clone = prototype.Clone();
...
}
public IPrototype Clone()
{
return this.MemberwiseClone();
}
Prototype – attention
• Maitriser la duplication pour ne pas dégrader la performance
Use Case

Faire du shopping
• Un client commande des articles sur internet
• Statuts de la commande :
• En cours : le client est en train de choisir les articles
• Validée : le client valide et paye la commande
• Livrée : le client reçoit les articles
Memento
• Sauvegarder et restaurer l’état d’un objet sans en violer
l’encapsulation
Originator
- state
+ SetMemento(Memento);
+ CreateMemento();
Memento
- state
+ GetState()
CareTaker
public void SetMemento(Memento memento)
{
state = memento.GetState();
}
public Memento CreateMemento()
{
return new Memento(state);
}
Memento – use cases
• Quand l’état interne d’un objet (totalement ou partiellement) doit
être mémorisé afin de pouvoir être restauré ultérieurement sans que
l’encapsulation de cet objet ne doive être brisée
Originator
- state
+ SetMemento(Memento);
+ CreateMemento();
Memento
- state
+ GetState()
CareTaker
public void SetMemento(Memento memento)
{
state = memento.GetState();
}
public Memento CreateMemento()
{
return new Memento(state);
}
Use Case

L’usine à chaussures
• Ajouter un nouveau type : botte de pluie
• Complexité combinatoire
IShoe
Sandal StreetShoe
LeatherSandal SyntheticSandal LeatherStreetShoe SyntheticStreetShoe
RainBoot
LeatherRainBoot SyntheticRainBoot
L’usine à chaussures
• Eviter la complexité combinatoire
<<Interface>>
IShoe
<<Interface>>
IMaterial
Sandal Shoe
RainBoot
Leather Synthetic
Bridge
• Séparer l’aspect d’implémentation d’un objet de son aspect de
représentation et d’interface
<<Interface>>
IAbstraction
+ DoOperation()
Client
<<Interface>>
IImplementor
+ DoOperationImplem()
RefinedAbstraction ConcreteImplementorA
+ DoOperationImplem()
ConcreteImplementorB
+ DoOperationImplem()
DoOperation()
{
implementor.DoOperationImplem();
}
Bridge – use cases
• Eviter une liaison forte entre la
représentation des objets et leur
implémentation
• Changer la représentation des
objets sans impacter les
interactions entre les objets et les
clients
• Garder la capacité d’extension par
la création de nouvelles sous-
classes
• Eviter d’obtenir des hiérarchies de
classes extrêmement complexes
<<Interface>>
IAbstraction
+ DoOperation()
Client
<<Interface>>
IImplementor
+ DoOperationImplem()
RefinedAbstraction ConcreteImplementorA
+ DoOperationImplem()
ConcreteImplementorB
+ DoOperationImplem()
DoOperation()
{
implementor.DoOperationImplem();
}
Use Case

Elements
• Changement de Write(), 3 fichiers touchés
Folder
+ Name : String
File
+ Name : String
<<Interface>>
IElement
+ Name : String
<<Interface>>
IReferenceableElement
Link
+ Name : String
References
+ Write()
+ Write() + Write() + Write()
Elements
Folder
+ Name : String
File
+ Name : String
<<Interface>>
IElement
+ Name : String
<<Interface>>
IReferenceableElement
Link
+ Name : String
References
+ Accept(IWriter writer)
+ Accept(IWriter writer) + Accept(IWriter writer) + Accept(IWriter writer)
Writer
+ Write(IElement element)
+ Write(Link link)
+ Writer(File file)
+ Write(Folder folder)
<<Interface>>
IWriter
+ Write(IElement element)
+ Write(Link link)
+ Writer(File file)
+ Write(Folder folder)
public Write(IElement element)
{
element.Accept(this);
}
public Write(Link link)
{
Console.WriteLine(link.Name);
}
...
public Accept(IWriter writer)
{
writer.Write(this);
}
Visitor
• Construire une opération à réaliser sur les éléments d’un ensemble
d’objets
• De nouvelles opérations peuvent ainsi être ajoutées sans modifier les
classes de ces objets <<Interface>>
IElement
+ AcceptVisitor(IVisitor visitor)
ConcreteElement1
+ AcceptVisitor(IVisitor visitor)
ConcreteElement2
+ AcceptVisitor(IVisitor visitor)
<<Interface>>
IVisitor
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
ConcreteVisitor1
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
ConcreteVisitor2
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
public AcceptVisitor(IVisitor visitor)
{
visitor.Visit(this);
}
Visitor – use case
• De nouvelles fonctionnalités doivent être ajoutées à un ensemble de
classes sans que ces ajouts viennent alourdir ces classes
• Un ensemble de classes possèdent une structure fixe et il est
nécessaire de leur adjoindre des fonctionnalités sans modifier leur
interface <<Interface>>
IElement
+ AcceptVisitor(IVisitor visitor)
ConcreteElement1
+ AcceptVisitor(IVisitor visitor)
ConcreteElement2
+ AcceptVisitor(IVisitor visitor)
<<Interface>>
IVisitor
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
ConcreteVisitor1
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
ConcreteVisitor2
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
public AcceptVisitor(IVisitor visitor)
{
visitor.Visit(this);
}
Visitor – attention
• Complexité
• Cycle de dépendance
• Il faut avoir des getters dans les classes utilisées
<<Interface>>
IElement
+ AcceptVisitor(IVisitor visitor)
ConcreteElement1
+ AcceptVisitor(IVisitor visitor)
ConcreteElement2
+ AcceptVisitor(IVisitor visitor)
<<Interface>>
IVisitor
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
ConcreteVisitor1
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
ConcreteVisitor2
+ Visit(ConcreteElement1 element)
+ Visit(ConcreteElement2 element)
public AcceptVisitor(IVisitor visitor)
{
visitor.Visit(this);
}
Use Case

A la crêperie
• Au menu, on trouve crêpe et gaufre.
• On peut y ajouter du chocolat, des fraises, de la chantilly …
• Le prix de la crêpe chocolat banane =
prix crêpe + prix chocolat + prix banane
A la crêperie
• Au menu, crêpe et gaufre avec supplément chocolat, bananes, fraises,
chantilly …
Crepe
+ GetPrice()
Waffle
+ GetPrice()
<<Interface>>
IDessert
+ GetPrice()
Extra
+ GetPrice()
Chocolate
+ GetPrice()
Chantilly
+ GetPrice()
Strawberry
+ GetPrice()
dessert
public GetPrice()
{
return this.price + this.dessert.GetPrice();
}
Decorator
• Ajouter dynamiquement des fonctionnalités supplémentaires à un
objet.
<<Interface>>
IComponent
+ DoSomething()
ConcreteComponent
+ DoSomething()
<<Interface>>
IDecorator
+ DoSomething()
Decorator
+ DoSomething()
public Decorator(IComponent component)
{
this.component = component;
}
public DoSomething()
{
...
this.component.DoSomething-);
...
}
Decorator – use case
• Ajouter dynamiquement des fonctionnalités à un objet sans modifier
son interface
• Gérer des fonctionnalités qui peuvent être retirées dynamiquement
• Eviter l’héritage complexe
<<Interface>>
IComponent
+ DoSomething()
ConcreteComponent
+ DoSomething()
<<Interface>>
IDecorator
+ DoSomething()
Decorator
+ DoSomething()
public Decorator(IComponent component)
{
this.component = component;
}
public DoSomething()
{
...
this.component.DoSomething-);
...
}
Decorator – attention
• Ce pattern ne traite pas l’ordre de composition ou de fabrication
<<Interface>>
IComponent
+ DoSomething()
ConcreteComponent
+ DoSomething()
<<Interface>>
IDecorator
+ DoSomething()
Decorator
+ DoSomething()
public Decorator(IComponent component)
{
this.component = component;
}
public DoSomething()
{
...
this.component.DoSomething-);
...
}
Use Case

Au roi du burger
• Constituer son burger
• Choisir le pain et ajouter des ingrédients avec type de portion
• Légère
• Normal
• Extra
Builder
• Construire des objets complexes sans préoccuper le client des
différentes implémentations
Director
+ Construct()
<<Interface>>
IBuilder
+ BuildFirstPart()
+ BuildSecondPart()
+ GetProduct()
ConcreteBuilder
+ BuildFirstPart()
+ BuildSecondPart()
+ GetProduct()
Product
Builder – use case
• Le client a besoin de construire un objet complexe sans connaitre son
implémentation
• Le client a besoin de construire des objets complexes ayant plusieurs
implémentations ou représentations
Director
+ Construct()
<<Interface>>
IBuilder
+ BuildFirstPart()
+ BuildSecondPart()
+ GetProduct()
ConcreteBuilder
+ BuildFirstPart()
+ BuildSecondPart()
+ GetProduct()
Product
Builder – attention
• Quand il s’agit d’une construction step by step
• Complexité du code
Director
+ Construct()
<<Interface>>
IBuilder
+ BuildFirstPart()
+ BuildSecondPart()
+ GetProduct()
ConcreteBuilder
+ BuildFirstPart()
+ BuildSecondPart()
+ GetProduct()
Product
Use Case

Un peu de mathématiques
• Réalisez l’expression suivante
(4 - 5) * 2
• L’idée est de pouvoir réaliser plusieurs
opérations à la suite
((4 - 5) * 2) + (4 * (1 + 6))
4 5
-1
-
2
-2
*
1 6
4
+
7
28
*
+
26
Un peu de mathématiques
Operand
+ Evaluate()
Operator
+ Evaluate()
<<Interface>>
IExpression
+ Evaluate()
PlusOperator
+ Evaluate()
MinusOperator
+ Evaluate()
2
#LeftExpression
#RightExpression
public Operand(double value)
{
this.operand = value;
}
public double Evaluate()
{
return this.operand;
}
public double Evaluate()
{
return this.leftExpression.Evaluate() +
this.rightExpression.Evaluate();
}
public Operator(IExpression leftExpression, IExpression rightExpression)
{
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
public abstract double Evaluate();
public double Evaluate()
{
return this.leftExpression.Evaluate() -
this.rightExpression.Evaluate();
}
Interpreter
• Définir une représentation de grammaire pour interpréter des
expressions
TerminalExpression
+ Interpret(Context)
NonTerminalExpression
+ Interpret(Context)
<<Interface>>
IExpression
+ Interpret(Context)
NonTerminalExpression1
+ Interpret(Context)
NonTerminalExpression2
+ Interpret(Context)
Interpreter – use cases
• Interpréter des expressions
représentées sous forme d’arbres
syntaxiques
• Quand la grammaire des expressions est
simple
• L’évaluation n’a pas besoin d’être rapide
• Si la grammaire est complexe, il vaut
mieux utiliser un analyseur
syntaxique
• Si l’évaluation doit être rapide, il vaut
mieux utiliser un compilateur
TerminalExpression
+ Interpret(Context)
NonTerminalExpression
+ Interpret(Context)
<<Interface>>
IExpression
+ Interpret(Context)
NonTerminalExpression1
+ Interpret(Context)
NonTerminalExpression2
+ Interpret(Context)
Use Case

Comportement graphique des sites web
Comportement graphique des sites web
• La modification d’une valeur d’un
widget peut conduire à modifier
l’aspect d’autres widget :
• Visible ou masqué
• Changement des valeurs d’un menu
• Changement du format des valeurs
• Inconvénient
• Chaque objet doit connaitre tous les
objets dépendants
• La réutilisabilité des objets est réduite
Widget 1
Widget 2
Widget 3
Widget 4
Widget 5
Widget 6
Mediator
• Construire un objet dont la vocation est la gestion et le contrôle des
interactions dans un ensemble d’objets sans que ses éléments
doivent se connaitre mutuellement.
<<Interface>>
Mediator
+ DoSomething()
<<Interface>>
Element
ConcreteElement1
ConcreteElement1
ConcreteMediator
Mediator – use cases
• Un système est formé d’un ensemble
d’objets basé sur une communication
complexe conduisant à associer de
nombreux objets entre eux
• Les objets d’un système sont difficiles
à réutiliser car ils possèdent de
nombreuses associations avec d’autres
objets
• La modularité d’un système est
médiocre, obligeant dans le cas d’une
adaptation d’une partie du système à
écrire de nombreuses sous classes.
<<Interface>>
Mediator
+ DoSomething()
<<Interface>>
Element
ConcreteElement1
ConcreteElement1
ConcreteMediator
Use Case

Distributeur de billets
Source : https://sourcemaking.com/design_patterns/chain_of_responsibility
Chain of responsibility
• Une chaine d’objets tel que si un objet ne peut pas répondre à une
requête, il puisse la transmettre à son successeur jusqu’à ce que l’un
des objets de la chaine y réponde.
Handler
+ HandleRequest()
successor
ConcreteHandler1
+ HandleRequest()
ConcreteHandler1
+ HandleRequest()
Client
Chain of responsibility – use cases
• Une chaine d’objets gère une requête selon un ordre qui es défini
dynamiquement
• La façon dont une chaine d’objets gère une requête ne doit pas être
connue par le client
Handler
+ HandleRequest()
successor
ConcreteHandler1
+ HandleRequest()
ConcreteHandler1
+ HandleRequest()
Client
Use Case

Composer son PC
• Choisir les options
• Taille écran : 11’, 16’ …
• Processeur : i5, i7 …
• Mémoire RAM : 12 Go, 16 Go …
• Taille du disque dur : 1To, SSD …
• Carte vidéo : NVIDIA, AMD …
• Casque : USB, Bluetooth …
• Souris : filaire, sans fil…
• Sac : à dos, sacoche …
• Clavier : Azerty, Querty
• Chaque option a un prix
• Le prix du PC = prix de base
(300€) + somme des options
Flyweight
• Permet de partager de façon efficace un ensemble important d’objets
de granularité fine
FlyweightFabric
+ GetFlyweight(key)
Flyweight
- intrinsicState
+ Operation(extrinsicState)
Client
if(flyweights.ContainsKey(key))
{
return flyweights[key];
}
else
{
var newFlyweight = new Flyweight();
flyweights.Add(key, newFlyweight);
return newFlyweight;
}
Flyweight – use cases
• Le système utilise un grand nombre d’objets
• Le stockage des objets est couteux à cause d’une grande quantité
• Il existe de nombreux ensembles d’objets qui peuvent être remplacés
par quelques objets partagés une fois qu’une partie de leur état est
rendue extrinsèque
FlyweightFabric
+ GetFlyweight(key)
Flyweight
- intrinsicState
+ Operation(extrinsicState)
Client
if(flyweights.ContainsKey(key))
{
return flyweights[key];
}
else
{
var newFlyweight = new Flyweight();
flyweights.Add(key, newFlyweight);
return newFlyweight;
}
Use Case

Chez le concessionnaire
• Un client veut passer une commande pour une voiture
• Il a le choix de payer au comptant ou à crédit
Chez le concessionnaire
• Un client veut passer une commande pour une voiture
• Il a le choix de payer au comptant ou à crédit
OrderCreator
+ CreateNewOrder()
- CreateOrder() : Order
Order
+ Pay();
+ IsValid() : bool
SpotOrder
+ Pay();
+ IsValid() : bool
ForwardOrder
+ Pay();
+ IsValid() : bool
public void CreateNewOrder()
{
Order order= CreateOrder();
if(order.IsValid())
{
order.Pay();
}
}
private Order CreateOrder()
{
if(paymentType == PaymentType.Spot)
{
return new SpotOrder();
}
else
{
return new ForwardOrder();
}
}
Chez le concessionnaire
BaseOrderCreator
+ CreateNewOrder()
# CreateOrder() : Order
SpotOrderCreator
# CreateOrder() : Order
Order
+ Pay();
+ IsValid() : bool
SpotOrder
+ Pay();
+ IsValid() : bool
ForwardOrder
+ Pay();
+ IsValid() : bool
ForwardOrderCreator
# CreateOrder() : Order
public void CreateNewOrder()
{
Order order= CreateOrder();
if(order.IsValid())
{
order.Pay();
}
}
protected Order CreateOrder()
{
return new SpotOrder();
}
protected Order CreateOrder()
{
return new ForwardOrder();
}
AbstractCreator
+ CreateProduct() : IProduct
Creator
+ CreateProduct() : IProduct
IProduct
Product
Factory Method
• Introduire une méthode abstraite de création d’un objet en reportant
aux sous-classes concrètes la création effective
AbstractCreator
+ CreateProduct() : IProduct
Creator
+ CreateProduct() : IProduct
IProduct
Product
Factory Method – use cases
• Une classe ne connait que les classes abstraites des objets avec
lesquels elle possède des relations
• Une classe veut transmettre à ses sous-classes les choix
d’instanciation en profitant du mécanisme de polymorphisme
Use Case

Période des soldes
• Le responsable du magasin a besoin
d’appliquer et annuler une réduction sur un
produit
• Aujourd’hui -20% sur le prix initial
• Demain -10% supplémentaires => -30% en tout
• Le lendemain annuler le -10% => -20% en tout
Command
• Permet de transformer une requête en un objet pour faciliter les
opérations comme l’annulation ou la mise en file des requêtes et leur
suivi
Command
+ Execute()
<<Interface>>
ICommand
+ Execute()
Invoker
+ SetCommand(ICommand)
+ ExecuteCommand()
IReceiver
+ Action()
receiver.Action();
Command – use cases
• Un objet doit être paramétré par un traitement à réaliser
• Les commandes
• À stocker dans une file
• À exécuter à tout moment ou plusieurs fois
• À Annuler
• À tracer dans un fichier de log
Command
+ Execute()
<<Interface>>
ICommand
+ Execute()
Invoker
+ SetCommand(ICommand)
+ ExecuteCommand()
IReceiver
+ Action()
receiver.Action();
Command – attention
• Les commandes peuvent être regroupées sous la forme d’une
transaction (un ensemble ordonné de commandes qui agissent sur
l’état d’un système, si l’une est annulée tout l’ensemble l’est aussi)
Command
+ Execute()
<<Interface>>
ICommand
+ Execute()
Invoker
+ SetCommand(ICommand)
+ ExecuteCommand()
IReceiver
+ Action()
receiver.Action();

Contenu connexe

Similaire à Design patterns

Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...
Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...
Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...Tarik Zakaria Benmerar
 
Spark - au dela du dataframe avec Tungsten et Catalyst
Spark - au dela du dataframe avec Tungsten et CatalystSpark - au dela du dataframe avec Tungsten et Catalyst
Spark - au dela du dataframe avec Tungsten et CatalystMathieu Goeminne
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationECAM Brussels Engineering School
 
SSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLSSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLHervé Leclerc
 
Découvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCLDécouvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCLDotNetHub
 
Modèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueModèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueVladyslav Riabchenko
 
Scala : programmation fonctionnelle
Scala : programmation fonctionnelleScala : programmation fonctionnelle
Scala : programmation fonctionnelleMICHRAFY MUSTAFA
 
Eric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharpEric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharpMSDEVMTL
 
Procédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénientsProcédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénientsDenis Voituron
 
Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Jean-Michel Doudoux
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introductionneuros
 
Héritage et Polymorphisme .pdf
Héritage et Polymorphisme .pdfHéritage et Polymorphisme .pdf
Héritage et Polymorphisme .pdfAabidiHafid
 

Similaire à Design patterns (20)

Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...
Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...
Design patterns et Design Emergeant - Micro Days - Modern Software Developmen...
 
Part1
Part1Part1
Part1
 
POO
POOPOO
POO
 
Spark - au dela du dataframe avec Tungsten et Catalyst
Spark - au dela du dataframe avec Tungsten et CatalystSpark - au dela du dataframe avec Tungsten et Catalyst
Spark - au dela du dataframe avec Tungsten et Catalyst
 
Single Page Application
Single Page ApplicationSingle Page Application
Single Page Application
 
Programmation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulationProgrammation orientée objet : Object, classe et encapsulation
Programmation orientée objet : Object, classe et encapsulation
 
De Java à .NET
De Java à .NETDe Java à .NET
De Java à .NET
 
JAVA, JDBC et liaison base de données
JAVA, JDBC et liaison base de donnéesJAVA, JDBC et liaison base de données
JAVA, JDBC et liaison base de données
 
Android ORMLite
Android   ORMLiteAndroid   ORMLite
Android ORMLite
 
SSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQLSSL 2011 : Présentation de 2 bases noSQL
SSL 2011 : Présentation de 2 bases noSQL
 
Découvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCLDécouvrez C# 4.0 et les améliorations apportées à la BCL
Découvrez C# 4.0 et les améliorations apportées à la BCL
 
Modèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueModèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratique
 
Qualité de code et bonnes pratiques
Qualité de code et bonnes pratiquesQualité de code et bonnes pratiques
Qualité de code et bonnes pratiques
 
Scala : programmation fonctionnelle
Scala : programmation fonctionnelleScala : programmation fonctionnelle
Scala : programmation fonctionnelle
 
Eric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharpEric Moreau: AOP in .Net sing PostSharp
Eric Moreau: AOP in .Net sing PostSharp
 
Procédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénientsProcédures CLR pour SQL Server : avantages et inconvénients
Procédures CLR pour SQL Server : avantages et inconvénients
 
Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introduction
 
Pensez objets avec java
Pensez objets avec javaPensez objets avec java
Pensez objets avec java
 
Héritage et Polymorphisme .pdf
Héritage et Polymorphisme .pdfHéritage et Polymorphisme .pdf
Héritage et Polymorphisme .pdf
 

Plus de Dorra BARTAGUIZ

Améliorer l'implémentation du feature flipping
Améliorer l'implémentation du feature flippingAméliorer l'implémentation du feature flipping
Améliorer l'implémentation du feature flippingDorra BARTAGUIZ
 
Sortons de la pyramide pour construire une stratégie de test
Sortons de la pyramide pour construire une stratégie de testSortons de la pyramide pour construire une stratégie de test
Sortons de la pyramide pour construire une stratégie de testDorra BARTAGUIZ
 
Living documentation au service de l'agilité
Living documentation au service de l'agilitéLiving documentation au service de l'agilité
Living documentation au service de l'agilitéDorra BARTAGUIZ
 
Devs, let's reclaim DDD!
Devs, let's reclaim DDD!Devs, let's reclaim DDD!
Devs, let's reclaim DDD!Dorra BARTAGUIZ
 
S'améliorer sans s'épuiser
S'améliorer sans s'épuiserS'améliorer sans s'épuiser
S'améliorer sans s'épuiserDorra BARTAGUIZ
 

Plus de Dorra BARTAGUIZ (8)

Améliorer l'implémentation du feature flipping
Améliorer l'implémentation du feature flippingAméliorer l'implémentation du feature flipping
Améliorer l'implémentation du feature flipping
 
Sortons de la pyramide pour construire une stratégie de test
Sortons de la pyramide pour construire une stratégie de testSortons de la pyramide pour construire une stratégie de test
Sortons de la pyramide pour construire une stratégie de test
 
Living documentation au service de l'agilité
Living documentation au service de l'agilitéLiving documentation au service de l'agilité
Living documentation au service de l'agilité
 
Devs, let's reclaim DDD!
Devs, let's reclaim DDD!Devs, let's reclaim DDD!
Devs, let's reclaim DDD!
 
Rendons le DDD aux devs
Rendons le DDD aux devsRendons le DDD aux devs
Rendons le DDD aux devs
 
S'améliorer sans s'épuiser
S'améliorer sans s'épuiserS'améliorer sans s'épuiser
S'améliorer sans s'épuiser
 
Slim down diet and tdd
Slim down diet and tddSlim down diet and tdd
Slim down diet and tdd
 
Slim down diet_ and tdd
Slim down diet_ and tddSlim down diet_ and tdd
Slim down diet_ and tdd
 

Dernier

GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...
GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...
GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...Institut de l'Elevage - Idele
 
comprehension de DDMRP dans le domaine de gestion
comprehension de DDMRP dans le domaine de gestioncomprehension de DDMRP dans le domaine de gestion
comprehension de DDMRP dans le domaine de gestionyakinekaidouchi1
 
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdfJTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdfInstitut de l'Elevage - Idele
 
GAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenus
GAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenusGAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenus
GAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenusInstitut de l'Elevage - Idele
 
JTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdfJTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdfInstitut de l'Elevage - Idele
 
JTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdfJTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdfInstitut de l'Elevage - Idele
 
GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...
GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...
GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...Institut de l'Elevage - Idele
 
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...Institut de l'Elevage - Idele
 
Algo II : les piles ( cours + exercices)
Algo II :  les piles ( cours + exercices)Algo II :  les piles ( cours + exercices)
Algo II : les piles ( cours + exercices)Sana REFAI
 
GAL2024 - Décarbonation du secteur laitier : la filière s'engage
GAL2024 - Décarbonation du secteur laitier : la filière s'engageGAL2024 - Décarbonation du secteur laitier : la filière s'engage
GAL2024 - Décarbonation du secteur laitier : la filière s'engageInstitut de l'Elevage - Idele
 
GAL2024 - L'élevage laitier cultive la biodiversité
GAL2024 - L'élevage laitier cultive la biodiversitéGAL2024 - L'élevage laitier cultive la biodiversité
GAL2024 - L'élevage laitier cultive la biodiversitéInstitut de l'Elevage - Idele
 
GAL2024 - Changements climatiques et maladies émergentes
GAL2024 - Changements climatiques et maladies émergentesGAL2024 - Changements climatiques et maladies émergentes
GAL2024 - Changements climatiques et maladies émergentesInstitut de l'Elevage - Idele
 
Câblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdfCâblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdfmia884611
 

Dernier (15)

GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...
GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...
GAL2024 - Renouvellement des actifs : un enjeu pour la filière laitière franç...
 
comprehension de DDMRP dans le domaine de gestion
comprehension de DDMRP dans le domaine de gestioncomprehension de DDMRP dans le domaine de gestion
comprehension de DDMRP dans le domaine de gestion
 
CAP2ER_GC_Presentation_Outil_20240422.pptx
CAP2ER_GC_Presentation_Outil_20240422.pptxCAP2ER_GC_Presentation_Outil_20240422.pptx
CAP2ER_GC_Presentation_Outil_20240422.pptx
 
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdfJTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
JTC 2024 - SMARTER Retour sur les indicateurs de santé .pdf
 
GAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenus
GAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenusGAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenus
GAL2024 - Situation laitière 2023-2024 : consommation, marchés, prix et revenus
 
JTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdfJTC 2024 - Réglementation européenne BEA et Transport.pdf
JTC 2024 - Réglementation européenne BEA et Transport.pdf
 
JTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdfJTC 2024 La relance de la filière de la viande de chevreau.pdf
JTC 2024 La relance de la filière de la viande de chevreau.pdf
 
GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...
GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...
GAL2024 - Traite des vaches laitières : au coeur des stratégies d'évolution d...
 
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
JTC 2024 - Leviers d’adaptation au changement climatique, qualité du lait et ...
 
Algo II : les piles ( cours + exercices)
Algo II :  les piles ( cours + exercices)Algo II :  les piles ( cours + exercices)
Algo II : les piles ( cours + exercices)
 
GAL2024 - Décarbonation du secteur laitier : la filière s'engage
GAL2024 - Décarbonation du secteur laitier : la filière s'engageGAL2024 - Décarbonation du secteur laitier : la filière s'engage
GAL2024 - Décarbonation du secteur laitier : la filière s'engage
 
GAL2024 - L'élevage laitier cultive la biodiversité
GAL2024 - L'élevage laitier cultive la biodiversitéGAL2024 - L'élevage laitier cultive la biodiversité
GAL2024 - L'élevage laitier cultive la biodiversité
 
GAL2024 - Changements climatiques et maladies émergentes
GAL2024 - Changements climatiques et maladies émergentesGAL2024 - Changements climatiques et maladies émergentes
GAL2024 - Changements climatiques et maladies émergentes
 
JTC 2024 - DeCremoux_Anomalies_génétiques.pdf
JTC 2024 - DeCremoux_Anomalies_génétiques.pdfJTC 2024 - DeCremoux_Anomalies_génétiques.pdf
JTC 2024 - DeCremoux_Anomalies_génétiques.pdf
 
Câblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdfCâblage, installation et paramétrage d’un réseau informatique.pdf
Câblage, installation et paramétrage d’un réseau informatique.pdf
 

Design patterns

  • 2. Qui suis-je ? • Dorra BARTAGUIZ • Software craftswoman • Tech lead • Coach technique • Peu importe le langage • .Net, java, php, python, js dorra.bartaguiz@outlook.com
  • 3. Programme Du code C# à faire/factoriser Contexte Problématique Extraire le design pattern
  • 5. Design pattern - Définition • Modèle de conception • Décrit les cas d’utilisation • Sert d’abstraction au modèle d’implémentation • Intension, motivation, solution • Une solution à un problème générique
  • 6. Premier exemple • Projet à récupérer de GitHub • https://github.com/iAmDorra/DesignPatterns Folder + Name : String File + Name : String contains contains
  • 7. Solution & Projet • Définir le projet (ou les) de démarrage • Références d’un projet • Un autre projet • Une librairie du Framework • Un composant COM • … Project 1 Project 2 References Solution Project 3 References Project 4 2 1 1' 3 References x Build order
  • 8. Premier exemple • Contexte : • Un dossier peut contenir des fichiers et des dossiers Folder + Name : String File + Name : String contains contains
  • 9. Premier exemple • Inconvénients : • Pour connaitre le contenu de Folder, il faut parcourir les deux listes Folder + Name : String File + Name : String contains contains
  • 10. Premier exemple • Pour connaitre le contenu de Folder, il faut parcourir une seule collection Folder + Name : String File + Name : String <<Interface>> IElement + Name : String
  • 11. Premier exemple • Caractéristiques • Eviter la duplication • Extensible => Pattern « Composite » Folder + Name : String File + Name : String contains contains Folder + Name : String File + Name : String <<Interface>> IElement + Name : String
  • 12. Exercice • Ajouter un lien (Link) • Un lien peut référencer un fichier ou un dossier (pas les deux) • Un dossier peut contenir des liens Folder + Name : String File + Name : String <<Interface>> IElement + Name : String
  • 14. SOLID • S RP : Single Responsibility Principle • O CP : Open Close Principle • L SP : Liskov Substitution Principle • I SP : Interface Separation Principle • D IP : Dependency Inversion Principle
  • 15. Classification des patterns • GoF (Gang of four) classification • Creational patterns (de construction) • Behavior patterns (de comportement) • Structural patterns (de structuration)
  • 16. Revenons à nos moutons 
  • 17. Composite • Permettre à un client d’interagir avec un objet sans connaitre la profondeur de sa composition • Limiter les dépendances entre les classes concrètes • Eviter la duplication • Extensible Folder + Name : String File + Name : String <<Interface>> IElement + Name : String
  • 18. Composite – use cases • Il est nécessaire de représenter des hiérarchies de composition • Les clients de la composition doivent ignorer s’ils communiquent avec des objets composés ou non Folder + Name : String File + Name : String <<Interface>> IElement + Name : String
  • 20. Le système solaire • Il est composé de : • Le soleil • Des planètes • Autres étoiles et objets célestes
  • 21. Le système solaire Sun - instance : Sun + GetInstance() : Sun private static Sun instance = new Sun(); private Sun() { } public static Sun GetInstance() { return instance; }
  • 22. Singleton • Assurer qu’une classe ne possède qu’une seule instance et de fournir une méthode de classe unique retournant cette instance Singleton - instance : Singleton + GetInstance() : Singleton private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return instance; }
  • 23. Singleton – use cases • Il ne doit y avoir qu’une seule instance • Cette instance n’est accessible qu’à travers une méthode de classe • Eviter une variable globale Singleton - instance : Singleton + GetInstance() : Singleton private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return instance; }
  • 24. Singleton – use cases On peut avoir une version lazy du singleton Singleton - instance : Singleton + GetInstance() : Singleton private static Singleton instance; public static Singleton GetInstance() { if(instance == null) instance = new Singleton(); return instance }
  • 25. Singleton – attention • Si on est en multithreading, ajout un lock pour l’instance • Eviter les méthodes qui set l’instance à null Singleton - instance : Singleton + GetInstance() : Singleton + Reset() public static Singleton GetInstance() { if(instance == null) instance = new Singleton(); return instance } public void Reset() { instance = null; } var first = Singleton.GetInstance(); // first pointe donc sur un objet en mémoire first .Reset(); var second = Singleton.GetInstance(); // => on a donc deux instances en mémoire
  • 27. Appel au service client • Un client achète un article sur un site et paye par carte bancaire • Il veut changer l’adresse de livraison et rajouter une option dans l’article • Le changement d’adresse est au service de facturation • L’ajout de l’option est au service de commande • Il appelle le service client qui se charge de tout
  • 28. Appel au service client CustomerService + UpdateAdress(Client client, Adress newAdress) + AddOption(Order order, Option option) Billing + AddOption(Order order, Option option) + Edit(Order order) Ordering +UpdateAdress(Client client, Adress newAdress) Uses public void UpdateAdress(Client client, Adress newAdress) { ordering.UpdateAdress(client, newAdress); } public void AddOption(Order order, Option option) { billing.AddOption(order, option); }
  • 29. Façade • Créer une interface unifiée au sous-système • Un objet composé de plusieurs services Facade + RunMethod1(parameter1, parameter2) + RunMethod3() + RunMethod4(parameter3) Service3 + RunMethod4(parameter3) + RunMethod5(parameter) Service2 + RunMethod3() Service1 + RunMethod1(parameter1, parameter2) + RunMethod2()
  • 30. Façade – use cases • Dissimuler/faciliter au client la complexité des activités internes • Besoin de contrôler les modes d’accès aux composants • Un point d’entrée au sous-système Facade + RunMethod1(parameter1, parameter2) + RunMethod3() + RunMethod4(parameter3) Service3 + RunMethod4(parameter3) + RunMethod5(parameter) Service2 + RunMethod3() Service1 + RunMethod1(parameter1, parameter2) + RunMethod2()
  • 31. Façade – attention • Fort couplage • Degré de dépendance d’un module vis-à- vis d’un autre • Faible cohésion • Degré de cohérence des responsabilités d’un module Facade + RunMethod1(parameter1, parameter2) + RunMethod3() + RunMethod4(parameter3) Service3 + RunMethod4(parameter3) + RunMethod5(parameter) Service2 + RunMethod3() Service1 + RunMethod1(parameter1, parameter2) + RunMethod2()
  • 33. Compresser des données • On a besoin de compresser des données • Codage par répétition • AAA0000111FF => 3A40312F • Codage entropique (de Huffman ou arithmétique) • Pattern => 000 001 11 11 010 011 10
  • 34. Compresser des données Compressor + string Compress(string data) <<Interface>> ICompressor + string Compress(string data) public string Compress(string data) { switch (this.compressionType) { case CompressionType.Repetition: return CompressWithRepetitionAlgo(data); case CompressionType.Entropic: return CompressWithEntropicAlgo(data); case CompressionType.ByDictionary: return CompressByDictionaryAlgo(data); default: return data; } }
  • 35. Compresser des données RepetitionCompressor + string Compress(string data) <<Interface>> ICompressor + string Compress(string data) EntropicCompressor + string Compress(string data) Context - compressor : ICompressor + string Compress(string data) ByDictionaryCompressor + string Compress(string data) public string Compress(string data) { compressor.Compress(data); }
  • 36. Strategy • Adapter le comportement d’un objet en fonction d’un besoin sans changer les interactions de cet objet avec les clients • Représenter les comportements variables sous forme de classes • Les comportements/algorithmes sont interchangeables ConcreteStrategyA + Calculate() <<Interface>> Strategy + Calculate() ConcreteStrategyB + Calculate() Context + Execute() void Execute() { strategy.Calculate(); }
  • 37. Strategy – use cases • Besoin d’implémenter plusieurs comportements pour un traitement • Protéger les variations en séparant les parties variantes et invariantes ConcreteStrategyA + Calculate() <<Interface>> Strategy + Calculate() ConcreteStrategyB + Calculate() Context + Execute() void Execute() { strategy.Calculate(); }
  • 38. Strategy – attention • Quand les contextes sont responsables du choix de la stratégie ConcreteStrategyA + Calculate() <<Interface>> Strategy + Calculate() ConcreteStrategyB + Calculate() Context + Execute() void Execute() { strategy.Calculate(); }
  • 40. Chez le concessionnaire • Le concessionnaire gère les commandes issues de client de la France et du Luxembourg. • La différence entre les commandes concerne le calcul de la TVA • France : TVA = 19,6% • Luxembourg : TVA = 12% pour les prestations et 15% pour le matériel
  • 41. Chez le concessionnaire • Montant = HT + TVA <<Interface>> IOrder +CalculateAmount() FrenchOrder -preTaxAmount +CalculateAmount() LuxembourgishOrder -preTaxServiceAmount -preTaxMaterialAmount +CalculateAmount() public double CalculateAmount() { var vatAmount = preTaxAmount * 0.196; var amount = preTaxAmount + vatAmount; return amount; } public double CalculateAmount() { var vatAmount = preTaxServiceAmount * 0.12 + preTaxMaterialAmount * 0.15; var preTaxAmount = preTaxServiceAmount + preTaxMaterialAmount; var amount = preTaxAmount + vatAmount; return amount; }
  • 42. Chez le concessionnaire • Montant = HT + TVA • Extraire les méthodes • Mieux voir les factorisations futures <<Interface>> IOrder +CalculateAmount() FrenchOrder -preTaxAmount +CalculateAmount() LuxembourgishOrder -preTaxServiceAmount -preTaxMaterialAmount +CalculateAmount() public double CalculateAmount() { var amount = CalculatePreTaxAmount()+ CalculateVat(); return amount; } private double CalculateVat() { return preTaxAmount * 0.196; } private double CalculatePreTaxAmount() { return preTaxAmount; } public double CalculateAmount() { var amount = CalculatePreTaxAmount()+ CalculateVat(); return amount; } private double CalculateVat() { return preTaxServiceAmount * 0.12 + preTaxMaterialAmount * 0.15; } private double CalculatePreTaxAmount() { return preTaxServiceAmount + preTaxMaterialAmount; }
  • 43. Chez le concessionnaire • Montant = HT + TVA • Factoriser le comportement dans la classe de base • Implémenter les spécificités dans les classes filles <<Interface>> IOrder +CalculateAmount() FrenchOrder -preTaxAmount #CalculateVat() #CalculatePreTaxAmount() LuxembourgishOrder -preTaxServiceAmount -preTaxMaterialAmount #CalculateVat() #CalculatePreTaxAmount() <<Abstract>> BaseOrder +CalculateAmount() #CalculateVat() #CalculatePreTaxAmount() protected override double CalculateVat() { return preTaxAmount * 0.196; } protected override double CalculatePreTaxAmount() { return preTaxAmount; } protected override double CalculateVat() { return preTaxServiceAmount * 0.12 + preTaxMaterialAmount * 0.15; } protected override double CalculatePreTaxAmount() { return preTaxServiceAmount + preTaxMaterialAmount; } public double CalculateAmount() { return CalculateVat() + CalculatePreTaxAmount(); } protected abstract double CalculateVat(); protected abstract double CalculatePreTaxAmount();
  • 44. Template method • Reporter aux filles certaines étapes d’un traitement • Les étapes sont implémentées dans les classes filles ConcreteClass #Operation1() #Operation2() <<Abstract>> BaseClass +TemplateMethod() #Operation1() #Operation2() public void TemplateMethod() { ... Operation1(); ... Operation2(); ... } protected abstract void Operation1(); protected abstract void Operation2(); protected override void Operation1() { ... } protected override void Operation2() { ... }
  • 45. Template method – use cases • Deux classes ou plusieurs partagent du code identique • Les parties spécifiques déplacées dans les filles • Un algorithme avec une partie invariable et des parties spécifiques à différents objets ConcreteClass #Operation1() #Operation2() <<Abstract>> BaseClass +TemplateMethod() #Operation1() #Operation2() public void TemplateMethod() { ... Operation1(); ... Operation2(); ... } protected abstract void Operation1(); protected abstract void Operation2(); protected override void Operation1() { ... } protected override void Operation2() { ... }
  • 47. L’usine à chaussures • L’usine crée • Des chaussures de ville, des sandales • En cuir ou synthétiques ShoeCreator + CreateLeatherShoe() + CreateLeatherSandal() + CreateSyntheticShoe() + CreateSyntheticSandal() IShoe -type Client Sandal -type StreetShoe -type public StreetShoe CreateLeatherShoe() { return new StreetShoe(ShoeType.Leather); } public Sandal CreateSyntheticSandal() { return new Sandal(ShoeType.Synthetic); }
  • 48. L’usine à chaussures ShoeCreator + CreateShoe() + CreateSandal() IShoe Client Sandal StreetShoe LeatherFabric + CreateShoe() + CreateSandal() SyntheticFabric + CreateShoe() + CreateSandal() LeatherSandal SyntheticSandal LeatherStreetShoe SyntheticStreetShoe public StreetShoe CreateShoe() { return new LeatherStreetShoe(); } public Sandal CreateSandal() { return new LeatherSandal(); } public StreetShoe CreateShoe() { return new SyntheticStreetShoe(); } public Sandal CreateSandal() { return new SyntheticSandal(); }
  • 49. Abstract factory • Créer des objets regroupés en familles sans devoir connaître les classes concrètes destinées à la création de ces objets • Configuration flexible • Les implémentations doivent changer en fonction de certains paramètres AbstractFabric + CreateProductA() + CreateProductB() Client ProductA ProductB ConcreteFabric1 + CreateProductA() + CreateProductB() ConcreteFabric2 + CreateProductA() + CreateProductB() ProductA1 ProductA2 ProductB1 ProductB2
  • 50. Abstract factory – use cases • Un système utilisant des produits a besoin d’être indépendant de la façon dont ces produits sont créés et regroupés • Un système est paramétré par plusieurs familles de produits qui peuvent évoluer AbstractFabric + CreateProductA() + CreateProductB() Client ProductA ProductB ConcreteFabric1 + CreateProductA() + CreateProductB() ConcreteFabric2 + CreateProductA() + CreateProductB() ProductA1 ProductA2 ProductB1 ProductB2
  • 51. Abstract factory - attention • Si une règle de gestion exige de ne pas pouvoir créer des sandales en synthétique par exemple, ce pattern ne correspond pas car on va implémenter la méthode CreateSandal pour le synthétique • Risque de créer des objets incompatibles entre eux AbstractFabric + CreateProductA() + CreateProductB() Client ProductA ProductB ConcreteFabric1 + CreateProductA() + CreateProductB() ConcreteFabric2 + CreateProductA() + CreateProductB() ProductA1 ProductA2 ProductB1 ProductB2
  • 53. Faire du shopping • Un client commande des articles sur internet • Statuts de la commande : • En cours : le client est en train de choisir les articles • Validée : le client valide et paye la commande • Livrée : le client reçoit les articles
  • 54. Faire du shopping • Inconvénients • Il faut gérer tous les statuts dans les méthodes • Les transitions des statuts sont gérées par la commande Order - state - items + AddItem() + RemoveItem() + NextState() public void AddItem(Item item) { if(state == InProgress) { items.Add(item); } else { throw new System.NotSupportedException(); } } public void RemoveItem(Item item) { if(state == InProgress || state == Validated) { items.Remove(item); } else { throw new System.NotSupportedException(); } }
  • 55. Faire du shopping • Inconvénients • Il faut gérer tous les statuts dans les méthodes • Les transitions des statuts sont gérées par la commande • Nouvel objet à chaque modif de statut Order -state -items +AddItem() +RemoveItem() +NextState() InprogressOrder +AddItem() +RemoveItem() ValidatedOrder +AddItem() +RemoveItem() DeliveredOrder +AddItem() +RemoveItem() public void AddItem(Item item) { throw new NotSupportedException(); } public void RemoveItem(Item item) { throw new NotSupportedException(); } public void AddItem(Item item) { throw new NotSupportedException(); } public void RemoveItem(Item item) { items.Remove(item); } public void AddItem(Item item) { items.Add(item); } public void RemoveItem(Item item) { items.Remove(item); }
  • 56. Faire du shopping • Inconvénients • Il faut gérer tous les statuts dans les méthodes • Les transitions des statuts sont gérées par la commande • Nouvel objet à chaque modif de statut OrderStatus +AddItem() +RemoveItem() InprogressStatus +AddItem() +RemoveItem() ValidatedStatus +AddItem() +RemoveItem() DeliveredStatus +AddItem() +RemoveItem() Order -state -items +AddItem() +RemoveItem() +NextState() public void AddItem(Item item) { throw new NotSupportedException(); } public void RemoveItem(Item item) { throw new NotSupportedException(); } public void AddItem(Item item) { throw new NotSupportedException(); } public void RemoveItem(Item item) { items.Remove(item); } public void AddItem(Item item) { items.Add(item); } public void RemoveItem(Item item) { items.Remove(item); } public void AddItem(Item item) { state.AddItem(item); } public void RemoveItem(Item item) { state.RemoveItem(item); }
  • 57. State • Permet à un objet (Context) d’adapter son comportement en fonction de son état interne Context +Request() State +Handle() ConcreteStateA +Handle() ConcreteStateB +Handle() Request() { state.Handle(); }
  • 58. State – use cases • Le comportement d’un objet dépend de son état • L’implémentation par des instructions conditionnelles est trop complexe Context +Request() State +Handle() ConcreteStateA +Handle() ConcreteStateB +Handle() Request() { state.Handle(); }
  • 59. State – attention • Ne pas implémenter si deux états (simples) Context +Request() State +Handle() ConcreteStateA +Handle() ConcreteStateB +Handle() Request() { state.Handle(); }
  • 61. Comparateur d'hôtels • J’ai créé un service de comparaison des hôtels du coin • Je veux cherche des clients potentiels pour mon service Comparator + GetAvailableRooms(Date) : List<RoomPrice> <<Interface>> IComparator + GetAvailableRooms(Date) : List<RoomPrice>
  • 62. Comparator + GetAvailableRooms(Date) : List<RoomPrice> Client <<Interface>> IComparator + GetRoomAvailailities(Date) : List<RoomAvailability> <<Interface>> IComparator + GetAvailableRooms(Date) : List<RoomPrice> Comparateur d'hôtels • Le client impose un contrat de service qui lui correspond ?
  • 63. Comparateur d'hôtels • Le client impose un contrat de service qui lui correspond Comparator + GetAvailableRooms(Date) : List<RoomPrice> Client <<Interface>> IComparator + GetRoomAvailailities(Date) : List<RoomAvailability> <<Interface>> IComparator + GetAvailableRooms(Date) : List<RoomPrice> ComparatorAdaptor + GetRoomAvailailities(Date) : List<RoomAvailability>
  • 64. Adapter • Convertir une class existante en une interface attendue par les clients également existants afin qu’ils puissant travailler ensemble Adaptee + SpecificRequest() Client <<Interface>> ITarget + Request() Adapter + Request() adaptee.SpecificRequest()
  • 65. Adapter – use cases • Intégrer dans un système un objet dont l’interface ne correspond pas à l’interface requise au sein de ce système • Fournir des interfaces multiples à un objet lors de sa conception Adaptee + SpecificRequest() Client <<Interface>> ITarget + Request() Adapter + Request() adaptee.SpecificRequest()
  • 66. Adapter – attention • Il y aura autant d’adaptateurs que de fournisseur Adaptee + SpecificRequest() Client <<Interface>> ITarget + Request() Adapter + Request() adaptee.SpecificRequest()
  • 68. Compter le nombre de LIKE • Dans mon application, j’ai un service pour liker mon produit • Créer un service de comptage LikeCounter + CountLikes() ProductAnalysis + LikeProduct()
  • 69. Compter le nombre de LIKE LikeCounter + Update(int) <<Interface>> ILikeCounter + Update(int) ProductAnalysis - List<ILikeCounter> counters + Add(ILikeCounter) + LikeProduct() public void Add(ILikeCounter counter) { counters.Add(counter); } public void LikeProduct() { likesNumber ++; foreach(var counter in this.counters) { counter.Update(likesNumber); } } public LikeCounter(ProductAnalysis product) { product.Add(this); } public void Update(int number) { Console.WriteLine(number); }
  • 70. Observer • Permet aux observateurs de mettre à jour leur état quand le sujet est modifié <<abstract>> Subject + Add(Observer) + Remove(Observer) + Notify() ConcretSubject - subjectState + GetState() <<abstract>> Observer + Update() ConcreteObserver - observerState + Update() subject observer return subjectState; public void Add(Observer observer) { this.observers.Add(observer); } public void Notify() { foreach(var obs in observers) { obs.Update(); } } public void Update() { observerState = subject.GetState(); }
  • 71. Observer – use cases • La modification d’un objet engendre des modifications dans d’autres objets qui sont déterminés dynamiquement • Un objet veut prévenir d’autres objets sans devoir connaitre leur type • pas de couplage <<abstract>> Subject + Add(Observer) + Remove(Observer) + Notify() ConcretSubject - subjectState + GetState() <<abstract>> Observer + Update() ConcreteObserver - observerState + Update() subject observer return subjectState; public void Add(Observer observer) { this.observers.Add(observer); } public void Notify() { foreach(var obs in observers) { obs.Update(); } } public void Update() { observerState = subject.GetState(); }
  • 72. Observer – Attention • Plusieurs implémentations • Garder le statut dans le sujet et l’appeler dans la méthode Update de l’observer • Ne pas exposer le statut du sujet et envoyer Event (contient les infos de notification) <<abstract>> Subject + Add(Observer) + Remove(Observer) + Notify(Event) <<abstract>> Observer + Update(Event) ConcreteObserver - observerState + Update(Event) observer public void Add(Observer observer) { this.observers.Add(observer); } public void Notify(Event e) { foreach(var obs in observers) { obs.Update(e); } } public void Update(Event e) { observerState = e; }
  • 74. Composer son PC • Choisir les options • Taille écran : 11’, 16’ … • Processeur : i5, i7 … • Mémoire RAM : 12 Go, 16 Go … • Taille du disque dur : 1To, SSD … • Carte vidéo : NVIDIA, AMD … • Casque : USB, Bluetooth … • Souris : filaire, sans fil… • Sac : à dos, sacoche … • Clavier : Azerty, Querty • Chaque option a un prix • Le prix du PC = prix de base (300€) + somme des options
  • 76. Chez le dentiste • L’assistante accueille les patients par ordre d’arrivée • Le dentiste ne sait pas s’il y a un patient qui attend, ni qui il est • Il demande de faire entrer le suivant • Il ne s’intéresse pas à la façon dont la salle d’attente est gérée. Dentist + EnterNext() Patient - name works with Secretary - patients : Collection<Patient> + HasNext() : bool + Next() : Patient
  • 77. Chez le dentiste • Introduire la notion de collection pour dissocier la collection en tant que tel et la manière de la parcourir • Si on change la règle d’itération par arrivée en itération par priorité Dentist + EnterNext() Patient - name works with Secretary + HasNext() : bool + Next() : Patient Patients +
  • 78. Chez le dentiste Dentist + EnterNext() Secretary + HasNext() : bool + Next() : Patient Patients + GetIterator() : IIterator <<Interface>> IIterable + GetIterator() : IIterator <<Interface>> IIterator + HasNext() : bool + Next() : IElement implements <<Interface>> IElement Name Patient Name instanciate IIterator GetIterator() { return new Secretary(); } void EnterNext() { IIterator iterator = this.patients.GetIterator(); if(iterator.HasNext()) { this.Receive(iterator.Next()); } }
  • 79. Iterator • Fournir un accès séquentiel à une collection à des clients sans que ceux-ci doivent se préoccuper de l’implémentation de cette collection • Parcours séquentiel / variable • Enumération Client + DoSomething() ConcreteIterator<Element> + HasNext() : bool + Next() : Element ConcreteIterable + GetIterator() : IIterator<IElement> <<Interface>> IIterable + GetIterator() : IIterator<IElement> <<Interface>> IIterator<IElement> + HasNext() : bool + Next() : IElement implements <<Interface>> IElement Element instanciate void DoSomething() { IIterator<IElement> iterator = this.iterable.GetIterator(); if(iterator.HasNext()) { this.Receive(iterator.Next()); } }
  • 80. Iterator – use cases • Parcours du contenu d’une collection sans accéder à sa représentation interne • Gérer plusieurs parcours simultanément Client + DoSomething() ConcreteIterator<Element> + HasNext() : bool + Next() : Element ConcreteIterable + GetIterator() : IIterator<IElement> <<Interface>> IIterable + GetIterator() : IIterator<IElement> <<Interface>> IIterator<IElement> + HasNext() : bool + Next() : IElement implements <<Interface>> IElement Element instanciate void DoSomething() { IIterator<IElement> iterator = this.iterable.GetIterator(); if(iterator.HasNext()) { this.Receive(iterator.Next()); } }
  • 81. Iterator – Attention • L’ordre n’est pas maitrisé par le client mais plutôt par l’itérateur Client + DoSomething() ConcreteIterator<Element> + HasNext() : bool + Next() : Element ConcreteIterable + GetIterator() : IIterator<IElement> <<Interface>> IIterable + GetIterator() : IIterator<IElement> <<Interface>> IIterator<IElement> + HasNext() : bool + Next() : IElement implements <<Interface>> IElement Element instanciate void DoSomething() { IIterator<IElement> iterator = this.iterable.GetIterator(); if(iterator.HasNext()) { this.Receive(iterator.Next()); } }
  • 83. Catalogue de films • Au lieu de charger tout le film en mémoire, on affiche une image • Un clic sur la photo permet de jouer le film • But : réduire la quantité de mémoire utilisée
  • 84. Catalogue de films • Au lieu de charger tout le film en mémoire, on affiche une image • Un clic sur la photo permet de jouer le film • But : réduire la quantité de mémoire utilisée Animation + Show() + Clic() Film + Show() + Clic() + Run() AnimationSubstitute # photo + Show() + Clic() 0..1 #film public void Show() { if(film == null) photo.Show(); else film.Show(); } public void Clic() { if(film == null) { film = new Film(); } film.Run(); }
  • 85. Proxy • Concevoir un objet qui se substitue à un autre et qui en contrôle l’accès <<Interface>> ISubject + DoSomething() RealSubject + DoSomething() Proxy - wrapee + DoSomething() Client public void DoSomething() { // Optionnal functionnality wrapee.DoSomething(); // Optionnal functionnality }
  • 86. Proxy – use cases • Proxy virtuel : créer un objet de taille importante au moment approprié • Proxy remote : accéder à un objet s’exécutant sur un autre environnement • Proxy de protection : sécuriser l’accès à un objet (authentification) <<Interface>> ISubject + DoSomething() RealSubject + DoSomething() Proxy - wrapee + DoSomething() Client public void DoSomething() { // Optionnal functionnality wrapee.DoSomething(); // Optionnal functionnality }
  • 88. Chez le grossiste de fournitures bureau • Tous les mois, l’école passe la même commande de fournitures (stylo, feutres, papiers …) • Afin de faciliter la saisie pour ses clients, le grossiste a décidé de fournir une fonctionnalité de duplication de commande passée
  • 89. Chez le grossiste de fournitures bureau • Fonctionnalité de duplication de commande <<Interface>> ICloneableOrder + Clone() Order + Clone() Client + CreateOrderFromAnother() order public void CreateOrderFromAnother() { ... var newOrder = order.Clone(); ... } public ICloneableOrder Clone() { return this.MemberwiseClone(); }
  • 90. Prototype • Créer de nouveaux objets par duplication d’objets existants qui disposent de la capacité de clonage <<Interface>> IPrototype + Clone() ContretePrototype1 + Clone() ContretePrototype2 + Clone() Client + Operation() prototype public void Operation() { ... var clone = prototype.Clone(); ... } public IPrototype Clone() { return this.MemberwiseClone(); }
  • 91. Prototype – uses cases • Créer des instances sans connaitre la hiérarchie des classes <<Interface>> IPrototype + Clone() ContretePrototype1 + Clone() ContretePrototype2 + Clone() Client + Operation() prototype public void Operation() { ... var clone = prototype.Clone(); ... } public IPrototype Clone() { return this.MemberwiseClone(); }
  • 92. Prototype – attention • Maitriser la duplication pour ne pas dégrader la performance
  • 94. Faire du shopping • Un client commande des articles sur internet • Statuts de la commande : • En cours : le client est en train de choisir les articles • Validée : le client valide et paye la commande • Livrée : le client reçoit les articles
  • 95. Memento • Sauvegarder et restaurer l’état d’un objet sans en violer l’encapsulation Originator - state + SetMemento(Memento); + CreateMemento(); Memento - state + GetState() CareTaker public void SetMemento(Memento memento) { state = memento.GetState(); } public Memento CreateMemento() { return new Memento(state); }
  • 96. Memento – use cases • Quand l’état interne d’un objet (totalement ou partiellement) doit être mémorisé afin de pouvoir être restauré ultérieurement sans que l’encapsulation de cet objet ne doive être brisée Originator - state + SetMemento(Memento); + CreateMemento(); Memento - state + GetState() CareTaker public void SetMemento(Memento memento) { state = memento.GetState(); } public Memento CreateMemento() { return new Memento(state); }
  • 98. L’usine à chaussures • Ajouter un nouveau type : botte de pluie • Complexité combinatoire IShoe Sandal StreetShoe LeatherSandal SyntheticSandal LeatherStreetShoe SyntheticStreetShoe RainBoot LeatherRainBoot SyntheticRainBoot
  • 99. L’usine à chaussures • Eviter la complexité combinatoire <<Interface>> IShoe <<Interface>> IMaterial Sandal Shoe RainBoot Leather Synthetic
  • 100. Bridge • Séparer l’aspect d’implémentation d’un objet de son aspect de représentation et d’interface <<Interface>> IAbstraction + DoOperation() Client <<Interface>> IImplementor + DoOperationImplem() RefinedAbstraction ConcreteImplementorA + DoOperationImplem() ConcreteImplementorB + DoOperationImplem() DoOperation() { implementor.DoOperationImplem(); }
  • 101. Bridge – use cases • Eviter une liaison forte entre la représentation des objets et leur implémentation • Changer la représentation des objets sans impacter les interactions entre les objets et les clients • Garder la capacité d’extension par la création de nouvelles sous- classes • Eviter d’obtenir des hiérarchies de classes extrêmement complexes <<Interface>> IAbstraction + DoOperation() Client <<Interface>> IImplementor + DoOperationImplem() RefinedAbstraction ConcreteImplementorA + DoOperationImplem() ConcreteImplementorB + DoOperationImplem() DoOperation() { implementor.DoOperationImplem(); }
  • 103. Elements • Changement de Write(), 3 fichiers touchés Folder + Name : String File + Name : String <<Interface>> IElement + Name : String <<Interface>> IReferenceableElement Link + Name : String References + Write() + Write() + Write() + Write()
  • 104. Elements Folder + Name : String File + Name : String <<Interface>> IElement + Name : String <<Interface>> IReferenceableElement Link + Name : String References + Accept(IWriter writer) + Accept(IWriter writer) + Accept(IWriter writer) + Accept(IWriter writer) Writer + Write(IElement element) + Write(Link link) + Writer(File file) + Write(Folder folder) <<Interface>> IWriter + Write(IElement element) + Write(Link link) + Writer(File file) + Write(Folder folder) public Write(IElement element) { element.Accept(this); } public Write(Link link) { Console.WriteLine(link.Name); } ... public Accept(IWriter writer) { writer.Write(this); }
  • 105. Visitor • Construire une opération à réaliser sur les éléments d’un ensemble d’objets • De nouvelles opérations peuvent ainsi être ajoutées sans modifier les classes de ces objets <<Interface>> IElement + AcceptVisitor(IVisitor visitor) ConcreteElement1 + AcceptVisitor(IVisitor visitor) ConcreteElement2 + AcceptVisitor(IVisitor visitor) <<Interface>> IVisitor + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) ConcreteVisitor1 + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) ConcreteVisitor2 + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) public AcceptVisitor(IVisitor visitor) { visitor.Visit(this); }
  • 106. Visitor – use case • De nouvelles fonctionnalités doivent être ajoutées à un ensemble de classes sans que ces ajouts viennent alourdir ces classes • Un ensemble de classes possèdent une structure fixe et il est nécessaire de leur adjoindre des fonctionnalités sans modifier leur interface <<Interface>> IElement + AcceptVisitor(IVisitor visitor) ConcreteElement1 + AcceptVisitor(IVisitor visitor) ConcreteElement2 + AcceptVisitor(IVisitor visitor) <<Interface>> IVisitor + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) ConcreteVisitor1 + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) ConcreteVisitor2 + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) public AcceptVisitor(IVisitor visitor) { visitor.Visit(this); }
  • 107. Visitor – attention • Complexité • Cycle de dépendance • Il faut avoir des getters dans les classes utilisées <<Interface>> IElement + AcceptVisitor(IVisitor visitor) ConcreteElement1 + AcceptVisitor(IVisitor visitor) ConcreteElement2 + AcceptVisitor(IVisitor visitor) <<Interface>> IVisitor + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) ConcreteVisitor1 + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) ConcreteVisitor2 + Visit(ConcreteElement1 element) + Visit(ConcreteElement2 element) public AcceptVisitor(IVisitor visitor) { visitor.Visit(this); }
  • 109. A la crêperie • Au menu, on trouve crêpe et gaufre. • On peut y ajouter du chocolat, des fraises, de la chantilly … • Le prix de la crêpe chocolat banane = prix crêpe + prix chocolat + prix banane
  • 110. A la crêperie • Au menu, crêpe et gaufre avec supplément chocolat, bananes, fraises, chantilly … Crepe + GetPrice() Waffle + GetPrice() <<Interface>> IDessert + GetPrice() Extra + GetPrice() Chocolate + GetPrice() Chantilly + GetPrice() Strawberry + GetPrice() dessert public GetPrice() { return this.price + this.dessert.GetPrice(); }
  • 111. Decorator • Ajouter dynamiquement des fonctionnalités supplémentaires à un objet. <<Interface>> IComponent + DoSomething() ConcreteComponent + DoSomething() <<Interface>> IDecorator + DoSomething() Decorator + DoSomething() public Decorator(IComponent component) { this.component = component; } public DoSomething() { ... this.component.DoSomething-); ... }
  • 112. Decorator – use case • Ajouter dynamiquement des fonctionnalités à un objet sans modifier son interface • Gérer des fonctionnalités qui peuvent être retirées dynamiquement • Eviter l’héritage complexe <<Interface>> IComponent + DoSomething() ConcreteComponent + DoSomething() <<Interface>> IDecorator + DoSomething() Decorator + DoSomething() public Decorator(IComponent component) { this.component = component; } public DoSomething() { ... this.component.DoSomething-); ... }
  • 113. Decorator – attention • Ce pattern ne traite pas l’ordre de composition ou de fabrication <<Interface>> IComponent + DoSomething() ConcreteComponent + DoSomething() <<Interface>> IDecorator + DoSomething() Decorator + DoSomething() public Decorator(IComponent component) { this.component = component; } public DoSomething() { ... this.component.DoSomething-); ... }
  • 115. Au roi du burger • Constituer son burger • Choisir le pain et ajouter des ingrédients avec type de portion • Légère • Normal • Extra
  • 116. Builder • Construire des objets complexes sans préoccuper le client des différentes implémentations Director + Construct() <<Interface>> IBuilder + BuildFirstPart() + BuildSecondPart() + GetProduct() ConcreteBuilder + BuildFirstPart() + BuildSecondPart() + GetProduct() Product
  • 117. Builder – use case • Le client a besoin de construire un objet complexe sans connaitre son implémentation • Le client a besoin de construire des objets complexes ayant plusieurs implémentations ou représentations Director + Construct() <<Interface>> IBuilder + BuildFirstPart() + BuildSecondPart() + GetProduct() ConcreteBuilder + BuildFirstPart() + BuildSecondPart() + GetProduct() Product
  • 118. Builder – attention • Quand il s’agit d’une construction step by step • Complexité du code Director + Construct() <<Interface>> IBuilder + BuildFirstPart() + BuildSecondPart() + GetProduct() ConcreteBuilder + BuildFirstPart() + BuildSecondPart() + GetProduct() Product
  • 120. Un peu de mathématiques • Réalisez l’expression suivante (4 - 5) * 2 • L’idée est de pouvoir réaliser plusieurs opérations à la suite ((4 - 5) * 2) + (4 * (1 + 6)) 4 5 -1 - 2 -2 * 1 6 4 + 7 28 * + 26
  • 121. Un peu de mathématiques Operand + Evaluate() Operator + Evaluate() <<Interface>> IExpression + Evaluate() PlusOperator + Evaluate() MinusOperator + Evaluate() 2 #LeftExpression #RightExpression public Operand(double value) { this.operand = value; } public double Evaluate() { return this.operand; } public double Evaluate() { return this.leftExpression.Evaluate() + this.rightExpression.Evaluate(); } public Operator(IExpression leftExpression, IExpression rightExpression) { this.leftExpression = leftExpression; this.rightExpression = rightExpression; } public abstract double Evaluate(); public double Evaluate() { return this.leftExpression.Evaluate() - this.rightExpression.Evaluate(); }
  • 122. Interpreter • Définir une représentation de grammaire pour interpréter des expressions TerminalExpression + Interpret(Context) NonTerminalExpression + Interpret(Context) <<Interface>> IExpression + Interpret(Context) NonTerminalExpression1 + Interpret(Context) NonTerminalExpression2 + Interpret(Context)
  • 123. Interpreter – use cases • Interpréter des expressions représentées sous forme d’arbres syntaxiques • Quand la grammaire des expressions est simple • L’évaluation n’a pas besoin d’être rapide • Si la grammaire est complexe, il vaut mieux utiliser un analyseur syntaxique • Si l’évaluation doit être rapide, il vaut mieux utiliser un compilateur TerminalExpression + Interpret(Context) NonTerminalExpression + Interpret(Context) <<Interface>> IExpression + Interpret(Context) NonTerminalExpression1 + Interpret(Context) NonTerminalExpression2 + Interpret(Context)
  • 126. Comportement graphique des sites web • La modification d’une valeur d’un widget peut conduire à modifier l’aspect d’autres widget : • Visible ou masqué • Changement des valeurs d’un menu • Changement du format des valeurs • Inconvénient • Chaque objet doit connaitre tous les objets dépendants • La réutilisabilité des objets est réduite Widget 1 Widget 2 Widget 3 Widget 4 Widget 5 Widget 6
  • 127. Mediator • Construire un objet dont la vocation est la gestion et le contrôle des interactions dans un ensemble d’objets sans que ses éléments doivent se connaitre mutuellement. <<Interface>> Mediator + DoSomething() <<Interface>> Element ConcreteElement1 ConcreteElement1 ConcreteMediator
  • 128. Mediator – use cases • Un système est formé d’un ensemble d’objets basé sur une communication complexe conduisant à associer de nombreux objets entre eux • Les objets d’un système sont difficiles à réutiliser car ils possèdent de nombreuses associations avec d’autres objets • La modularité d’un système est médiocre, obligeant dans le cas d’une adaptation d’une partie du système à écrire de nombreuses sous classes. <<Interface>> Mediator + DoSomething() <<Interface>> Element ConcreteElement1 ConcreteElement1 ConcreteMediator
  • 130. Distributeur de billets Source : https://sourcemaking.com/design_patterns/chain_of_responsibility
  • 131. Chain of responsibility • Une chaine d’objets tel que si un objet ne peut pas répondre à une requête, il puisse la transmettre à son successeur jusqu’à ce que l’un des objets de la chaine y réponde. Handler + HandleRequest() successor ConcreteHandler1 + HandleRequest() ConcreteHandler1 + HandleRequest() Client
  • 132. Chain of responsibility – use cases • Une chaine d’objets gère une requête selon un ordre qui es défini dynamiquement • La façon dont une chaine d’objets gère une requête ne doit pas être connue par le client Handler + HandleRequest() successor ConcreteHandler1 + HandleRequest() ConcreteHandler1 + HandleRequest() Client
  • 134. Composer son PC • Choisir les options • Taille écran : 11’, 16’ … • Processeur : i5, i7 … • Mémoire RAM : 12 Go, 16 Go … • Taille du disque dur : 1To, SSD … • Carte vidéo : NVIDIA, AMD … • Casque : USB, Bluetooth … • Souris : filaire, sans fil… • Sac : à dos, sacoche … • Clavier : Azerty, Querty • Chaque option a un prix • Le prix du PC = prix de base (300€) + somme des options
  • 135. Flyweight • Permet de partager de façon efficace un ensemble important d’objets de granularité fine FlyweightFabric + GetFlyweight(key) Flyweight - intrinsicState + Operation(extrinsicState) Client if(flyweights.ContainsKey(key)) { return flyweights[key]; } else { var newFlyweight = new Flyweight(); flyweights.Add(key, newFlyweight); return newFlyweight; }
  • 136. Flyweight – use cases • Le système utilise un grand nombre d’objets • Le stockage des objets est couteux à cause d’une grande quantité • Il existe de nombreux ensembles d’objets qui peuvent être remplacés par quelques objets partagés une fois qu’une partie de leur état est rendue extrinsèque FlyweightFabric + GetFlyweight(key) Flyweight - intrinsicState + Operation(extrinsicState) Client if(flyweights.ContainsKey(key)) { return flyweights[key]; } else { var newFlyweight = new Flyweight(); flyweights.Add(key, newFlyweight); return newFlyweight; }
  • 138. Chez le concessionnaire • Un client veut passer une commande pour une voiture • Il a le choix de payer au comptant ou à crédit
  • 139. Chez le concessionnaire • Un client veut passer une commande pour une voiture • Il a le choix de payer au comptant ou à crédit OrderCreator + CreateNewOrder() - CreateOrder() : Order Order + Pay(); + IsValid() : bool SpotOrder + Pay(); + IsValid() : bool ForwardOrder + Pay(); + IsValid() : bool public void CreateNewOrder() { Order order= CreateOrder(); if(order.IsValid()) { order.Pay(); } } private Order CreateOrder() { if(paymentType == PaymentType.Spot) { return new SpotOrder(); } else { return new ForwardOrder(); } }
  • 140. Chez le concessionnaire BaseOrderCreator + CreateNewOrder() # CreateOrder() : Order SpotOrderCreator # CreateOrder() : Order Order + Pay(); + IsValid() : bool SpotOrder + Pay(); + IsValid() : bool ForwardOrder + Pay(); + IsValid() : bool ForwardOrderCreator # CreateOrder() : Order public void CreateNewOrder() { Order order= CreateOrder(); if(order.IsValid()) { order.Pay(); } } protected Order CreateOrder() { return new SpotOrder(); } protected Order CreateOrder() { return new ForwardOrder(); }
  • 141. AbstractCreator + CreateProduct() : IProduct Creator + CreateProduct() : IProduct IProduct Product Factory Method • Introduire une méthode abstraite de création d’un objet en reportant aux sous-classes concrètes la création effective
  • 142. AbstractCreator + CreateProduct() : IProduct Creator + CreateProduct() : IProduct IProduct Product Factory Method – use cases • Une classe ne connait que les classes abstraites des objets avec lesquels elle possède des relations • Une classe veut transmettre à ses sous-classes les choix d’instanciation en profitant du mécanisme de polymorphisme
  • 144. Période des soldes • Le responsable du magasin a besoin d’appliquer et annuler une réduction sur un produit • Aujourd’hui -20% sur le prix initial • Demain -10% supplémentaires => -30% en tout • Le lendemain annuler le -10% => -20% en tout
  • 145. Command • Permet de transformer une requête en un objet pour faciliter les opérations comme l’annulation ou la mise en file des requêtes et leur suivi Command + Execute() <<Interface>> ICommand + Execute() Invoker + SetCommand(ICommand) + ExecuteCommand() IReceiver + Action() receiver.Action();
  • 146. Command – use cases • Un objet doit être paramétré par un traitement à réaliser • Les commandes • À stocker dans une file • À exécuter à tout moment ou plusieurs fois • À Annuler • À tracer dans un fichier de log Command + Execute() <<Interface>> ICommand + Execute() Invoker + SetCommand(ICommand) + ExecuteCommand() IReceiver + Action() receiver.Action();
  • 147. Command – attention • Les commandes peuvent être regroupées sous la forme d’une transaction (un ensemble ordonné de commandes qui agissent sur l’état d’un système, si l’une est annulée tout l’ensemble l’est aussi) Command + Execute() <<Interface>> ICommand + Execute() Invoker + SetCommand(ICommand) + ExecuteCommand() IReceiver + Action() receiver.Action();