Vous êtes sur la page 1sur 84

Design Patterns

E. RAMAT

Université du Littoral - Côte d’Opale

6 octobre 2010

E. Ramat (ULCO) Design Patterns 6 octobre 2010 1 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 2 / 84
Objectifs

Comprendre les bases de la philosophie des “formes de


conception” ;
Connaître le vocabulaire spécifique ;
Connaître quelques “patterns”
Concevoir objet différemment ;
Traduire les patterns en C++.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 3 / 84


Définition

Description d’une solution classique à un problème récurrent ;


Décrit une partie de la solution . . . avec des relations avec le
système et les autres parties . . . ;
C’est une technique d’architecture logicielle.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 4 / 84


Ce que ce n’est pas . . .

Une brique : un pattern dépend de son environnement ;


Une règle : un pattern ne peut pas s’appliquer mécaniquement ;
Une méthode : ne guide pas une prise de décision ; un pattern est
la décision prise.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 5 / 84


Avantages

Un vocabulaire commun ;
Capitalisation de l’expérience ;
Un niveau d’abstraction plus élevé qui permet d’élaborer des
constructions logicielles de meilleure qualité ;
Réduire la complexité ;
Guide/catalogue de solutions.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 6 / 84


Inconvénients

Effort de synthèse ; reconnaître, abstraire . . . ;


Apprentissage, expérience ;
Les patterns “se dissolvent” en étant utilisés.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 7 / 84


Description

nom : augmente le vocabulaire, réifie une idée de solution, permet


de mieux communiquer ;
problème : quand appliquer la forme, le contexte . . . ;
solution : les éléments de la solution, leurs relations,
responsabilités, collaborations. Pas de manière précise, mais
suggestives. . . ;
conséquences : résultats et compromis issus de l’application de la
forme.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 8 / 84


Bibliographie

La Bible : Design pattern: Elements of Reusable Object-Oriented


Software, E. Gamma, R. Helm, R. Johnson et J. Vlissides ;
Head First : Design Patterns, Eric Freeman et Elisabeth Freeman,
édition o’reilly ;
Modern C++ Design, Generic Programming and Design Patterns
Applied, Andrei Alexandrescu, C++ In-Depth Series, Bjarne
Stroustrup, 323 p., 2001 ;
Advanced C++ Programming Styles and Idioms, James O.
Coplien, édition Addison-Wesley, 544 p., 1991 ;
http://home.earthlink.net/ huston2/dp/patterns.html ;
http://www.vico.org/pages/PatronsDisseny.html

E. Ramat (ULCO) Design Patterns 6 octobre 2010 9 / 84


Types de design pattern

Création
I abstraire le processus d’instanciation ;
I rendre indépendant de la façon dont les objets sont créés,
composés, assemblés, représentés ;
I encapsuler la connaissance de la classe concrète qui instancie ;
I cacher ce qui est créé, qui crée, comment et quand.
Structure :
I comment les objets sont assemblés ;
Comportement, pour décrire :
I des algorithmes ;
I des comportements entre objets ;
I des formes de communication entre objets.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 10 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 11 / 84
Introduction

singleton : instance unique ;


factory method : constructeur virtuel ;
abstract factory : fabrique d’objets ;
prototype : construction à partir de prototypes ;

E. Ramat (ULCO) Design Patterns 6 octobre 2010 12 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 13 / 84
Singleton
Utilisation

on utilise le Singleton lorsque :


I il n’y a qu’une unique instance d’une classe et qu’elle doit être
accessible de manière connue ;
I une instance unique peut être sous-classée et que les clients
peuvent référencer cette extension sans avoir à modifier leur code ;
I l’instance doit disparaître à la fin du programme.
des exemples : l’horloge système, le manager d’imprimantes, le
clavier, le générateur aléatoire, . . .

E. Ramat (ULCO) Design Patterns 6 octobre 2010 14 / 84


Singleton
Première traduction C++

Singleton
class Singleton
{
public :
static Singleton * instance ()
{
if (! pInstance ) pInstance = new Singleton ;
return pInstance ;
}
// operations
private :
Singleton ();
Singleton ( const Singleton &);

static Singleton * pInstance ;


};

Singleton * Singleton :: pInstance = 0;

E. Ramat (ULCO) Design Patterns 6 octobre 2010 15 / 84


Singleton
Commentaires

un attribut statique (attribut de classe) pInstance ;


allocation dynamique du Singleton s’il n’existe pas ;
initialisation à nul du Singleton ;
les constructeurs sont privés pour éviter la création d’instance ;
inconvénients :
I le Singleton n’est jamais détruit ;
I cette implémentation supporte-t-elle l’héritage ? ;
I que se passe-t-il en multi-threading ?

E. Ramat (ULCO) Design Patterns 6 octobre 2010 16 / 84


Singleton
Deuxième traduction C++

Singleton
class Singleton
{
public :
static Singleton & instance ()
{
static Singleton pInstance ;
return pInstance ;
}
// operations
private :
Singleton ();
Singleton ( const Singleton &);
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 17 / 84


Singleton
Commentaires

une instance locale et statique pInstance ;


pInstance est créée au premier appel de la fonction instance() ;
pInstance est détruite à la fin de l’application ;
problème :
I s’il existe plusieurs classes de type singleton, l’ordre des
destructions n’est pas garanti ;
I des dépendances entre singletons peuvent exister.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 18 / 84


Singleton
La fonction instance()

intance()
static Singleton & instance ()
{
extern void _ _ C o n s t r u c t S i n g l e t o n ( void * memory );
extern void _ _ D e s t r o y S i n g l e t o n ();
static bool __initialized = false ;
static char __buffer [ sizeof ( Singleton )];
if (! __initialized )
{
_ _ C o n s t r u c t S i n g l e t o n ( __buffer );
atexit ( _ _ D e s t r o y S i n g l e t o n );
__initialized = true ;
}
return * r e i n t e r p r e t _ c a s t < Singleton * >( __buffer );
}

E. Ramat (ULCO) Design Patterns 6 octobre 2010 19 / 84


Singleton
Commentaires

les fonctions __ConstructSingleton et __DestroySingleton sont les


traductions C des appels au constructeur et au destructeur ;
la fonction C atexit enregistre le fait que la fonction passée en
paramètre doit être appelé à la fin du programme ;
reinterpret_cast < Singleton* > est un cast C sans contrôle
de type (contrairement à static_cast ou dynamic_cast).
problème : s’il existe des dépendances entre singletons.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 20 / 84


Singleton
Deuxième traduction C++ (version Meyer)

Singleton
template < t y p e n a m e T > class Singleton
{
public :
static T & instance ()
{
static T pInstance ;
return pInstance ;
}
// operations
private :
T ();
T ( const T &);
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 21 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 22 / 84
Factory Method
Utilisation

on utilise le Factory Method lorsque :


I l’on définit une interface pour créer un objet, mais on laisse les
sous-classes décident quelle classe doit être instantiée ;
I une classe ne peut anticiper la classe de l’objet qu’elle doit
construire ;
I une classe délègue la responsabilité de la création à ses
sous-classes, tout en concentrant l’interface dans une classe
unique ;
l’opérateur new est considéré comme inutilisable ;
aussi appelé virtual constructor ;
des exemples : un éditeur multi-documents où chaque type de
document a besoin d’un éditeur spécifique . . .

E. Ramat (ULCO) Design Patterns 6 octobre 2010 23 / 84


Factory Method
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 24 / 84


Factory Method
Exemple d’utilisation

Factory Method
class D oc um en t Ma na ge r
{
public :
Document * newDocument ();
virtual Document * crea teDocume nt () = 0;
private :
std :: list < Document * > listOfDocs ;
};
Document * Do cu me n tM an ag er :: newDocument ()
{
Document * pDoc = cre ateDocume nt ();

listOfDocs . push_back ( pDoc );


return pDoc ;
}
Document * G r a p h i c D o c u m e n t M a n a g e r :: crea teDocume nt ()
{
return new G ra ph icD oc um en t ;
}

E. Ramat (ULCO) Design Patterns 6 octobre 2010 25 / 84


Factory Method
Commentaires

la fonction createDocument remplace l’opérateur new ;


la fonction newDocument ne peut pas utiliser l’opérateur new car
elle ne connaît pas la classe concrète de l’objet à créer ;
la fonction createDocument est alors abstraite et déléguée aux
sous-classes.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 26 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 27 / 84
Abstract Factory
Utilisation

on utilise le Abstract Factory lorsque :


I l’on doit fournir une interface pour créer une famille de composants
interdépendants ou non sans spécifier leur classe d’appartenance
concrète ;
I un système doit être indépendant de la façon dont ses composants
sont créés, assemblés, représentés ;
I un système repose sur un composant d’une famille de composants ;
I on veut définir une interface unique à une famille de composants
concrets ;
I l’operateur new est considéré comme inutilisable ;
I Factory Method est similaire à Abstract Factory mais sans
l’hypothèse sur les familles.
des exemples : un éditeur multi-documents où chaque type de
document a besoin d’un éditeur spécifique . . .

E. Ramat (ULCO) Design Patterns 6 octobre 2010 28 / 84


Abstract Factory
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 29 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 30 / 84
Prototype
Utilisation

on utilise le Prototype lorsque :


I l’on spécifie les objets de l’application par prototypage ;
I et que l’on crée les nouveaux objets par copie des prototypes ;
I pour éviter une hiérarchie de Factory parallèle à une hiérarchie de
composants (comme dans le pattern Factory Method) ;
I l’operateur new est considéré comme inutilisable.
appelé aussi Exemplaire (voir Advanced C++ Programming Styles
and Idioms, James O. Coplien).

E. Ramat (ULCO) Design Patterns 6 octobre 2010 31 / 84


Prototype
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 32 / 84


Prototype
Première traduction C++

Prototype
class Shape
{
public :
virtual Shape * clone () const = 0;
};

class Line : public Shape


{
public :
virtual Line * clone () const
{
return new Line (* this );
}
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 33 / 84


Prototype
Commentaires

la fonction abstraite clone a été surchargé d’une façon spéciale


grâce à la notion de “covariant return type” ;
on doit retourner un pointeur sur un type dérivé du type initial ;
problème :
I s’il existe plusieurs niveaux d’héritage, il ne faut pas oublier de
surcharger la fonction clone dans les sous-sous-classes.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 34 / 84


Prototype
Contrôle de l’implémentation

Prototype
class Shape
{
public :
Shape * clone () const
{
Shape * pClone = doClone ();
assert ( typeid (* pClone ) == typeid (* this ));
return pClone ;
}
protected :
virtual Shape * doClone () = 0;
};

typeid
La fonction typeid permet d’accèder à l’identifiant du type réel de
l’objet.
E. Ramat (ULCO) Design Patterns 6 octobre 2010 35 / 84
Prototype
Commentaires

comment reconstruire un objet envoyé dans un flux (dans un


fichier, par exemple) en ne sachant seulement qu’il appartient à
une hiérachie de classes ?
Flux
class Drawing
{
public :
void save ( std :: ofstream & out );
void load ( std :: ifstream & in );
};

void Drawing :: save ( std :: ofstream & out )


{
// écrire une entête
for ( chaque élément du dessin )
{
( élément courant ) - > save ( out );
}
}
E. Ramat (ULCO) Design Patterns 6 octobre 2010 36 / 84
Prototype
Commentaires

la classe Drawing possède une liste hétérogène d’objets de type


Shape ;
l’enregistrement n’est pas un problème ;
il faut s’assurer que chaque objet (comme Drawing) possède un
identifiant et qu’il enregistre afin de retrouver le type de l’objet
enregistré ;
problème : comment automatiser la lecture et la reconstruction
des objets ?

E. Ramat (ULCO) Design Patterns 6 octobre 2010 37 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 38 / 84
Introduction

proxy : utiliser un composant intermédiaire pour accèder un autre


composant.
flyweight : externalisation de l’état et utilisation de représentants ;
adapter : obtenir un objet qui permet d’en utiliser un autre en
conformité avec une certaine interface ;
bridge : découplage de l’abstraction de l’implémentation ;
composite : objets composés d’objets homogènes ;
decorator : ajout dynamique de comportements ou d’états à un
composant ;
facade : interface simple pour un système complexe ;

E. Ramat (ULCO) Design Patterns 6 octobre 2010 39 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 40 / 84
Proxy
Utilisation

on utilise le Proxy lorsque l’on veut référencer un objet par un


moyen plus complexe qu’un “simple” pointeur :
I remote proxy : ambassadeur
I protection proxy : contrôle d’accès
I référence intelligente : persistence, comptage de références, . . .
un exemple : un objet qui reporte les opérations coûteuses au
moment où on utilise réellement les résultats de ces opérations
(chargement d’une image à la fin d’un document, . . . ).

E. Ramat (ULCO) Design Patterns 6 octobre 2010 41 / 84


Proxy
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 42 / 84


Proxy
Smart Pointers

les “smart pointers” sont des objets C++ qui simulent les pointeurs
classiques en implémentant les opérateurs -> et * ;
les compteurs de références font parti de cette catégorie ;
disponibles dans la glibmm : classe RefPtr.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 43 / 84


Proxy
Smart pointers - Code

Smart pointers
t e m p l a t e < class T > class SmartPtr
{
public :
e x p l i c i t SmartPtr ( T * pointee ) : pointee_ ( pointee );
SmartPtr & o p e r a t o r =( const SmartPtr & other );
~ SmartPtr ();
T & o p e r a t o r *() const
{
...
return * pointee_ ;
}
T * operator - >() const
{
...
return pointee_ ;
}
private :
T * pointee_ ;
...
};
E. Ramat (ULCO) Design Patterns 6 octobre 2010 44 / 84
Proxy
Commentaires

objectif principal : optimiser la présentation des objets en


mémoire ;
un seul représentant pour plusieurs références tant que le
représentant n’est pas modifié !
plusieurs stratégies :
I une copie à chaque invocation du constructeur par recopie (deep
copy) ;
I une copie seulement en cas de modification (copy on write) - les
fonctions non constantes ;

E. Ramat (ULCO) Design Patterns 6 octobre 2010 45 / 84


Proxy
Les compteurs de référence

trois stratégies, le smart pointer référence :


I un compteur et l’objet réel ;
I une structure composée d’un compteur et d’un pointeur sur l’objet
réel ;
I l’objet réel et l’objet réel embarque le compteur ;
les deux premiers ajoutent une indirection coûteuse ;
dans ce dernier cas, il faut modifier la classe d’appartenance de
l’objet.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 46 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 47 / 84
Flyweight
Utilisation

on utilise le Flyweight lorsque :


I on utilise beaucoup d’objets ;
I les coûts de sauvegarde sont élevés ;
I l’état des objets peut être externalisé (extrinsic) ;
I de nombreux groupes d’objets peuvent être remplacés par
quelques objets partagés une fois que les états sont externalisés ;
I l’application ne dépend pas de l’identité des objets ;
un exemple : les caractères manipulés dans un traitement de
texte ;
I chaque caractère correspond à un objet ayant une police de
caractères, une taille de caractères, et d’autres données de
formatage ;
I un long document contenant beaucoup de caractères ainsi
implémentés ...

E. Ramat (ULCO) Design Patterns 6 octobre 2010 48 / 84


Flyweight
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 49 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 50 / 84
Adapter
Utilisation

on utilise l’Adapter lorsque on veut utiliser :


I une classe existante dont l’interface ne convient pas ;
I plusieurs sous-classes mais il est coûteux de redéfinir l’interface de
chaque sous-classe en les sous-classant ;
I un “adapter” peut adapter l’interface au niveau du parent ;
appelé aussi “wrapper” ;
exemple : mise en “conformité” de composants d’origines
diverses.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 51 / 84


Adapter
Utilisation

identifier les composants impliqués : les composants qui sont


clients et les composants doivent être adapté ;
identifier les intefaces que les clients désirent ;
concevoir une classe “wrapper” qui réalise la correspondance
entre la nouvelle interface et celle des classes à adapter ;

E. Ramat (ULCO) Design Patterns 6 octobre 2010 52 / 84


Adapter
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 53 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 54 / 84
Bridge
Utilisation

On utilise Bridge lorsque :


I on veut éviter un lien permanent entre l’abstraction et l’implantation
(ex: l’implantation est choisie à l’exécution) ;
I l’abstraction et l’implantation sont toutes les deux susceptibles
d’être raffinées ;
I les modifications subies par l’implantation ou l’abstraction ne
doivent pas avoir d’impacts sur le client (pas de recompilation) ;
concept “Enveloppe/Lettre” de Coplien.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 55 / 84


Bridge
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 56 / 84


Bridge
Traduction C++

Bridge
class Time {
public :
Time () { }
Time ( int hr , int min ) { imp_ = new TimeImp ( hr , min ); }
virtual void tell () { imp_ - > tell (); }
protected :
TimeImp * imp_ ;
};

class TimeImp {
public :
TimeImp ( int hr , int min ) { hr_ = hr ; min_ = min ; }
virtual void tell () { cout << " time ␣ is ␣ " << setw (2)
<< setfill (48) << hr_
<< min_ << endl ; }
protected :
int hr_ , min_ ;
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 57 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 58 / 84
Composite
Utilisation

On utilise Composite lorsque l’on veut :


I représenter une hiérarchie d’objets ;
I représenter des compositions récursives ;
exemple : un système de fichiers, un répertoire est composé de
fichiers et de répertoire.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 59 / 84


Composite
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 60 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 61 / 84
Introduction

observer : relation entre des vues et un composant observé ;


MVC (Model-View-Controler) : idem à observer avec la notion de
contrôleur ;
visitor : séparation des algorithmes des structures de données sur
lesquels ils opérent.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 62 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 63 / 84
Observer
Utilisation

On utilise Observer lorsque :


I l’on veut définir des dépendances de type un à plusieurs entre
plusieurs composants ;
I un objet change d’état, tous les composants en dépendant sont
avertis et sont mis à jour automatiquement ;
c’est la partie “Vue” du pattern “Model-View-Controler” ;
exemple : un document et ses vues.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 64 / 84


Observer
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 65 / 84


Observer
Commentaires

le “sujet” est associé seulement à la classe de base Obverser ;


le “client” configure le nombre et le type d’observateurs ;
les observateurs s’enregistrent eux-mêmes auprès du “sujet” ;
le “sujet” envoie les événements à tous les observateurs
enregistrés.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 66 / 84


Observer
Traduction C++

Observer
class Observer
{
public :
virtual void update () = 0;
};
class Subject
{
private :
vector < Observer * > observers ;
public :
void attach ( Observer * observer ) {
vector < Observer * >:: iterator i ;
bool contained = false ;
for ( i = observers . begin (); i != observers . end (); ++ i )
if (* i == observer ) contained = true ;
if (! contained ) observers . push_back ( observer );
};
...

E. Ramat (ULCO) Design Patterns 6 octobre 2010 67 / 84


Observer
Traduction C++

Observer
...
void detach ( Observer * observer ) {
vector < Observer * >:: iterator i ;
for ( i = observers . begin (); i != observers . end (); ++ i )
if (* i == observer ) {
observers . erase ( i );
return ;
}
};

void notify () {
vector < Observer * >:: iterator i ;
for ( i = observers . begin (); i != observers . end (); ++ i )
(* i ) - > update ();
};
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 68 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 69 / 84
Model-View-Controler
Introduction

le modèle gère les données ;


la vue affiche les données ;
le contrôleur gère la communication et les mises à jour ;
origine : Smalltalk (Xerox Park, Palo Alto - Milieu des années 70)

E. Ramat (ULCO) Design Patterns 6 octobre 2010 70 / 84


Model-View-Controler
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 71 / 84


Model-View-Controler
Le modèle

le modèle contient la donnée ;


la mise à jour par update() ;
le renseignement par getValue().

E. Ramat (ULCO) Design Patterns 6 octobre 2010 72 / 84


Model-View-Controler
Traduction C++

Le modèle
class Model
{
private :
View * view ;
Controller * controller ;
public :
Model (): view (0) , controller (0) {}
View * getView () { return view ; }
void setView ( View * view ) { this - > view = view ; }
Controller * getController () { return controller ; }
void setController ( Controller * controller )
{ this - > controller = controller ; }
void update (...) { ... }
... getValue () { return ... }
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 73 / 84


Model-View-Controler
La vue

la vue affiche les composants et les données ;


la mise à jour du texte de l’étiquette est faite par update() ;
pour la notification de modifications, c’est le contrôleur qui écoute !
la vue se débrouille pour les obtenir.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 74 / 84


Model-View-Controler
Traduction C++

La vue
class View
{
private :
Controller * controller ;
Model * model ;
public :
View (): controller (0) , model (0) {}
Controller * getController () { return controller ; }
void setController ( Controller * controller )
{ this - > controller = controller ; }
Model * getModel () { return model ; }
void setModel ( Model * model ) { this - > model = model ; }
void update (...) { ... }
... getValue () { return ... }
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 75 / 84


Model-View-Controler
Le contrôleur

réveillé par les actions produites dans la vue ;


récupère des information dans la vue ;
met à jour le modèle ;
récupère la nouvelle valeur dans le modèle et la transmet pour
affichage à la vue.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 76 / 84


Model-View-Controler
Traduction C++

Le contrôleur
class Controller
{
private :
View * view ;
Model * model ;
public :
Controller (): view (0) , model (0) {}
View * getView () { return view ; }
void setView ( View * view ) { this - > view = view ; }
Model * getModel () { return model ; }
void setModel ( Model * model ) { this - > model = model ; }
void action ()
{
model - > update ( view . getValue ())
view - > update ( model . getValue ())
}
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 77 / 84


Plan
1 Introduction
2 Création
Singleton
Factory Method
Abstract Factory
Prototype
3 Structure
Proxy
Flyweight
Adapter
Bridge
Composite
4 Comportement
Observer
Model-View-Controler
Visitor
E. Ramat (ULCO) Design Patterns 6 octobre 2010 78 / 84
Visitor
Introduction

représenter une opération / un algorithme à appliquer sur les


éléments d’une structure ;
“visitor” vous permet de définir une nouvelle opération sans
changer les composants où ce nouvel élément doit être utilisé
donc sans compilation ;
mécanisme de "double dispatch"

E. Ramat (ULCO) Design Patterns 6 octobre 2010 79 / 84


Visitor
Diagramme UML

E. Ramat (ULCO) Design Patterns 6 octobre 2010 80 / 84


Visitor
Traduction C++

Les éléments
class Element
{
virtual ~ Element () {}
virtual void accept ( Visitor *) = 0;
};

class Foo : public Element


{
void make_foo () { cout << " Making ␣ some ␣ Foo ... " << endl ; }
virtual void accept ( Visitor * v ) { v - > visit ( this ); }
};

class Bar : public Element


{
void make_bar () { cout << " Making ␣ some ␣ Bar ... " << endl ; }
virtual void accept ( Visitor * v ) { v - > visit ( this ); }
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 81 / 84


Visitor
Traduction C++

Les "visitors"
class Visitor
{
virtual ~ Visitor () { }
virtual void visit ( Foo *) = 0;
virtual void visit ( Bar *) = 0;
};

class MakeVisitor : public Visitor


{
virtual void visit ( Foo * foo ) { foo - > make_foo (); }
virtual void visit ( Bar * bar ) { bar - > make_bar (); }
};

E. Ramat (ULCO) Design Patterns 6 octobre 2010 82 / 84


Visitor
Traduction C++

L’utilisation
int main ()
{
MakeVisitor v ;
Foo f ;
Bar b ;

f . accept (& v );
b . accept (& v );
return 0;
}

E. Ramat (ULCO) Design Patterns 6 octobre 2010 83 / 84


Visitor
Traduction C++

Explications
chaque type d’élément propose une méthode "make" et autorise
les "visitors" via la méthode accepte ;
la méthode "accept" propose au "visitor" d’éxecuter l’une de ses
opérations (sans savoir laquelle) ;
selon le visitor, la méthode "visit" va invoquer la méthode de
l’éléments spécifiquement à son objectif.

E. Ramat (ULCO) Design Patterns 6 octobre 2010 84 / 84