Vous êtes sur la page 1sur 45

1 Année master ISI

Notes de Cours
Conception avancée des logiciels

Cours 4
Design Patterns
(Patrons de conception)
Présenté par
Mr KHELIFA N.
Rappel
Objet

Objet: Entité avec une limite et


◦ une identité bien définie,
◦ qui encapsule un état et
◦ un comportement
Exemple
e3:Etudiant

Id: 11129 m1:Matiere esg1:Enseignat


Nom: Salim
Prénom: amir Id: 112 Id: 11166
Parcours: licence e4:Etudiant Nom: interface Nom: Mohamed
Année etude: 3 HM prénom: djaafar
e1:Etudiant Id: 11130 Label: IHM Grade:
CalculerMoy() Nom: Kaddour Parcours: licence Echelon : 3
Id: 11121 Revisercours() Prénom: hillal Année etude: 3
Nom: ahmed Parcours: licence Ensigne ()
Prénom: Okba Année etude: 3 Presenter()
Parcours: licence e2:Etudiant
Année etude: 3 CalculerMoy()
Id: 11125 Revisercours() m2:Matiere
CalculerMoy() Nom: kamal esg2:Enseignat
Revisercours() Prénom: khaled Id: 122
Parcours: licence Nom: Genie Id: 1177
Année etude: 3 Logicie Nom: Mohamed
Label: GL prénom: djaafar
CalculerMoy() Parcours: licence Grade:
Revisercours() Année etude: 3 Echelon : 3

Presenter() Ensigne ()
Classe
 Classe est une description d’un ensemble d’objets qui
partagent les mêmes caractéristiques (propriétés,
opérations,...) et la même sémantique
e3:Etudiant

Id: 11129
Nom: Salim e4:Etudiant Etudiant
e1:Etudiant Prénom: amir
Parcours: licence Id: 11130 Id: int
Id: 11121 Année etude: 3 Nom: Kaddour Nom: string
Nom: ahmed Prénom: hillal Prénom: string
Prénom: Okba CalculerMoy() Parcours: licence Parcours: string
Parcours: licence Revisercours() Année etude: 3 Année etude: int
Année etude: 3
CalculerMoy() CalculerMoy()
e2:Etudiant
CalculerMoy() Revisercours() Revisercours()
Revisercours()
Id: 11125
Nom: kamal
Prénom: khaled
Parcours: licence
Année etude: 3

CalculerMoy()
Revisercours()
Définitions
Quelques concepts sur les classes
◦ Attribut : Propriété nommée d’un classificateur qui
décrit une plage de valeur que les instance d’un
classificateur peuvent prendre

◦ Opération : Service qui peut être demandé à tout objet


de la classe

 La signature d'une opération: La signature d'une opération se


compose de son nom et de tous ses paramètres (y compris le
paramètre de retour, qui définit le type de retour de l'opération).

 méthode = implantation de l'opération


Classe abstraite

 Une opération est dite abstraite lorsqu’on connaît sa signature mais


pas la manière dont elle peut être réalisée (en UML, on écrit son
nom en italique).

 Il appartient aux classes enfant de définir les opérations abstraites.

 Une classe est dite abstraite lorsqu’elle définit au moins une


méthode abstraite ou lorsqu’une classe parent contient une méthode
abstraite non encore réalisée (en UML, on écrit son nom en
italique).

 Tant qu’au moins une méthode demeure abstraite (même héritée),


la classe ne peut être qu’abstraite.

 Il est impossible d’instancier directement une classe abstraite.


Exemple Classe abstraite
Interface
• Définition

• collection d’opérations abstraites cohérentes utilisée pour spécifier un service


proposé par un composant ou une classe

 les interfaces sont des éléments de modèle qui définissent des ensembles
d'opérations que d'autres éléments de modèle, tels que des classes ou des
composants, doivent implémenter.
 Un élément de modèle d'implémentation réalise une interface en remplaçant
chacune des opérations que l'interface déclare.
 Vous pouvez utiliser des interfaces dans les diagrammes de classes et les
diagrammes de composants pour spécifier un contrat entre l'interface et le
discriminant qui réalise l'interface
Exemple
Héritage vs Composition
Problème :
Modéliser le fait qu’il y a des voitures bleues, des voitures
rouges et des voitures vertes

 Solution 1 : Héritage
◦ Créer une classe abstraite Voiture
◦ Créer 3 classes VoitureBleue, VoitureRouge et VoitureVerte qui héritent de
Voiture

 Solution 2 : Composition
 Créer une classe Voiture et une classe Couleur
 Créer une association (composition) entre Voiture et Couleur
Héritage vs Délégation
Problème :
◦ Appeler dans une classe B une opération op() d’une classe A ?

 Solution 1 : Héritage
◦ Faire hériter B de A
◦ op() peut être appelée depuis n’importe quelle instance de B

 Solution 2 : Délégation
◦ Ajouter dans B un attribut a de type A (Ajouter une association de B vers A)
◦ a.op() peut être appelée depuis n’importe quelle instance de B
Concepts de base

Couplage
Cohésion
Couplage
Mesure de l’interdépendance entre deux
modules.
 Un ensemble de modules est faiblement couplé si les
liens de dépendances entre les modules sont peu
nombreux.
 Un faible couplage est précurseur…
D’un bon découpage du système: les éléments qui
dépendent les uns des autres ne sont pas «éparpillés» à
travers les modules du système.
D’une facilité de maintenance: une modification dans un
module affecte éventuellement un nombre restreint d’autres
modules. Nombre de révisions réduites…
Couplage
Cohésion
Un module est fortement cohésif si tous ses éléments
sont destinés et sont essentiels à la réalisation d’une
tâche commune unique.

Une forte cohésion est précurseur…


D’un bon découpage du système: les éléments qui ont rapport
les uns avec les autres se retrouvent dans un même module.
D’une facilité de maintenance: les éléments destinés à une
même tâche sont regroupés et ont peut facilement les
retrouver.
D’un faible couplage: les éléments inter-dépendants se
trouvant dans le même module, les dépendances inter-
modules sont moindres…
Quelques principes de conception
orientée objet
 Protection des variations : Identifier les points de variation et
d’évolution, et séparer ces aspects de ceux qui demeurent constants
 Faible couplage : Réduire l’impact des modifications en
minimisant les
dépendances entre classes
 Forte cohésion : Faciliter la compréhension, gestion et réutilisation
des
objets en concevant des classes à but unique
 Indirection : Limiter le couplage et protéger des variations en
ajoutant des objets intermédiaires

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


Principes de conception (1)
 Programmer pour une interface plus qu’une implémentation
 Limiter le couplage et protéger des variations en faisant
abstraction de l’implémentation

Le client se réfère a une interface et est indépendant


par rapport à l’implémentation
Exemple
• imaginez une classe abstraite Animal, avec deux implémentations concrètes,
Chien et Chat

supertype abstrait (peut


être une interface OU une
Implémentation concrète classe abstraite)

• On veut implémenter un chien qui aboi (diapo suivante)


Exemple
Programmer une implémentation donnerait le
code suivant :

◦ Chien c = new Chien ();


◦ c.aboyer();
Déclarer la variable “c” de type Chien (une
implémentation concrète d’Animal) nous
oblige à coder une implémentation concréte
Exemple
 programmer une interface ou un supertype donnerait
ceci :
◦ Animal animal = new Chien ();
◦ animal.emettreSon(); Nous savons que c’est un Chien, mais nous
pouvons maintenant utiliser la référence animal
de manière polymorphe.

Mieux encore, au lieu de coder en dur l’instanciation du


sous-type (comme new Chien ()) dans le code, affectez
l’objet de l’implémentation concrète au moment de
l’exécution : Nous ne savons pas QUEL EST le soustype
◦ a = getAnimal(); réel de l’animal... tout ce qui nous
intéresse, c’est qu’il sait comment répondre à
◦ a.emettreSon(); emettreSon().
Principes de conception (1.2)
 Utiliser des classes abstraites pour définir des
interfaces communes à un ensemble de
classes(interface client , interface entre classe )
Principes de conception (2)
 Préférer la composition d’objet à l’héritage de classes
 Utiliser la composition au lieu de l’héritage pour déléguer une
tâche à un objet, changer dynamiquement
le comportement d’une instance,
Conséquence
Concept 1
Les classes clients ou les objets sont
indépendants des classes qui implémentent
l’interface

Concept 2
Le comportement peut changer en cours
d’exécution
Les classes sont plus focalisées sur une tâche
Réduction des dépendances d’implémentation
Patron de conception
Un patron (pattern)

 Définition
1
Un pattern est une solution à un problème dans un contexte.

Définition 2
Un patron décrit à la fois un problème qui se produit très
fréquemment dans l’environnement et l’architecture de la
solution à ce problème de telle façon que l’on puisse utiliser
cette solution des milliers de fois sans jamais l’adapter deux
fois de la même manière.
Les patrons ne sont pas

Limités au domaine informatique

Des idées nouvelles

Des solutions qui n’ont fonctionné qu’une seule


fois

Des principes abstraits ou des heuristiques

Une panacée
Catégories de Patterns
 Architectural Patterns
– Schémas d’organisation structurelle de logiciels (pipes, filters,
brokers, blackboard, MVC, …)
• Design Patterns
– Caractéristiques clés d’une structure de conception commune
à plusieurs applications,
– Portée plus limitée que les « architectural patterns »
• Idioms ou coding patterns
– Solution liée à un langage particulier
• Anti-patterns
– Mauvaise solution ou comment sortir d ’une mauvaise
solution
• Organizational patterns
– Schémas d’organisation de tout ce qui entoure le
développement d’un logiciel (humains…..)
Patrons de base
Un patron de conception
(design pattern)
 Solutions abstraites qui fonctionnent bien dans différents contextes

 Décrit une structure commune et répétitive de composants en interaction


(la solution) qui résout un problème de conception dans un contexte
particulier.

 Des solutions éprouvées à des problèmes récurrents

 Spécifiques au domaine d’utilisation

 Une forme littéraire pour documenter des pratiques

 Un vocabulaire partagé pour discuter de problèmes

 Un moyen efficace de réutiliser et partager de l’expérience


Patron de conception dans le cycle de
développement

Intervienten conception détaillée


Reste indépendant du langage
d’implantation
Portée des Design Patterns
Portée de Classe
– Focalisation sur les relations entre
classes et leurs sous-classes
– Réutilisation par héritage

Portée d’Instance (objet)


– Focalisation sur les relations entre
les objets
– Réutilisation par composition
Catégories de patrons
Exemple
 Une boutique de vente des pizzas.
 Les deux classes principaux sont: pizzeria et pizza
 Nous pouvons écrire le code : commander pizza

Pizza commanderPizza() {
Pizza pizza = new Pizza();
pizza.preparer();
pizza.cuire();
pizza.couper();
pizza.emballer();
return pizza;
}}
Exemple(suite)
Mais un seul type de pizza ne suffit pas...
Pizza commanderPizza(String type) {
Maintenant, nous transmettons le
Pizza pizza; type de pizza à commanderPizza().
if (type.equals(“fromage”)) {
pizza = new PizzaFromage();
} else if (type.equals(“grecque”) {
pizza = new PizzaGrecque();
} else if (type.equals(“poivrons”) {
pizza = new PizzaPoivrons();
}
pizza.preparer();
pizza.cuire();
pizza.couper();
pizza.emballer();
return pizza;
}
Exemple(suite)
Pizza commanderPizza(String type) {
Pizza pizza;
Ce code n’est PAS
if (type.equals(“fromage”)) { fermé à la modification.
pizza = new PizzaFromage(); Si vous changez votre
} else if (type.equals(“grecque”) { carte, vous devrez
pizza = new PizzaGrecque(); reprendre ce code et le
} else if (type.equals(“poivrons”) { modifier
pizza = new PizzaPoivrons();
} else if (type.equals(“fruitsDeMer”) {
pizza = new PizzaFruitsDeMer();
} else if (type.equals(“vegetarienne”) {
pizza = new PizzaVegetarienne();
}
pizza.preparer();
pizza.cuire(); Voici ce qui ne devrait
pizza.couper(); pas changer.
pizza.emballer();
return pizza;
}
Exemple(suite)
Pizza commanderPizza(String type) {
Pizza pizza; if (type.equals(“fromage”)) {
pizza = new PizzaFromage();
} else if (type.equals(“poivrons”) {
pizza = new PizzaPoivrons();
} else if (type.equals(“fruitsDeMer”) {
pizza = new PizzaFruitsDeMer();
} else if (type.equals(“vegetarienne”) {
pizza = new PizzaVegetarienne();
}

pizza.preparer();
pizza.cuire();
pizza.couper(); nous plaçons ce code dans un
objet dont la seule responsabilité
pizza.emballer(); est de créer des pizzas.
Si un autre objet a besoin qu’une
return pizza; Nous avons un nom pour pizza soit créée, c’est
ce nouvel objet : à cet objet qu’il faut s’adresser.
} nous l’appelons une
Fabrique.
Exemple(suite)
public class SimpleFabriqueDePizzas {
creerPizza, C’est la
méthode que tous
public Pizza creerPizza(String type) {` les clients utiliseront
Pizza pizza = null; pour créer de
if (type.equals(“fromage”)) { nouvelles instances.

pizza = new PizzaFromage();


} else if (type.equals(“poivrons”)) {
pizza = new PizzaPoivrons();
} else if (type.equals(“fruitsDeMer”)) {
pizza = new PizzaFruitsDeMer();
}
return pizza;
}
 }
Exemple(suite)
public class Pizzeria { Nous donnons maintenant à
SimpleFabriqueDePizzas fabrique; Pizzeria une référence à une
SimpleFabriqueDePizzas

public Pizzeria(SimpleFabriqueDePizzas fabrique) {


this.fabrique = fabrique;
Nous transmettons la
} fabrique à
Pizzeria dans le
public Pizza commanderPizza(String type) { constructeur.
Pizza pizza;
pizza = fabrique.creerPizza(type);
pizza.preparer();
pizza.cuire();
Remarquez que nous avons remplacé
pizza.couper(); l’opérateur new par une méthode de
pizza.emballer(); création de l’objet fabrique. Nous
return pizza; n’avons plus d’instanciations concrètes
}
// autres méthodes
}
La Fabrique Simple n’est pas vraiment un Design
Pattern : c’est plutôt un idiome
Voici de laquelle
la fabrique dans programmation
nous .
créons les pizzas. Ce doit être la seule
partie de notre application qui se réfère à
des classes Pizza concrètes

Et voici le produit de la
fabrique :Nous avons défini
Pizza comme une
le client de la fabrique. classe abstraite
Pizzeria passe maintenant par la avec quelques
SimpleFabriqueDePizzas pour implémentations utiles
obtenir des instances de pizzas qui peuvent être
redéfinies

Et voilà nos produits concrets. Chacun doit implémenter l’interface


Pizza* (ce qui signifie en l’occurrence « étendre
la classe abstraite Pizza ») et être concret.
Tant que c’est le cas, il peut être créé par la fabrique et être
retourné au client.
Factory method
Problème
Une classe est incapable d’anticiper le type d’objets qu’elle
doit créer
Une classe désire laisser le choix du type d’objets créés à
ses sous-classes
Factory method
La fabrique est une classe qui
contient les implémentations de
toutes les méthodes destinées à
Fabrique
manipuler les produits, excepté la
Créer(): Produit méthode de fabrication.

La fabriqueConcret
implémente la méthode
Créer (), la méthode qui
crée réellement les produits

Tous les produits doivent


implémenter la même
interface, pour que les classes
qui utilisent
les produits puissent se référer
à l’interface, non à la classe
concrète.
Exemple
toutes deux ont
des classes abstraites qui
sont étendues par des
classes concrètes.
Les classes Produit

Les classes Créateur


Exemple 1
Exemple 2

Vous aimerez peut-être aussi