IPRO

Introduction aux Patrons de Conception

Guillaume Bouyer
ENSIIE

Plan du cours

Les patrons en programmation

Les patrons décrivent des solutions générales à des problèmes récurrents

  • Aide à la compréhension
  • Moyen de communication
  • Capitalisation de l'expérience en génie logiciel
  • Aide à la construction de logiciels

Types de patrons

Design Patterns
Structures de conception
Architectural Patterns
Schémas d'organisation structurelle du logiciel (haut niveau)
Ex : MVC
Idioms ou coding patterns
Solutions dans un langage particulier
Anti-patterns
Mauvaises solutions courantes (ou comment en sortir)
Organizational patterns
Schémas d'organisation (humaine) du développement

Design pattern

Solution générale à un problème courant en conception logicielle

  • Définition d'interactions entre des classes/objets
  • Indépendant du langage de programmation et du paradigme :
    • un design pattern s'adapte
    • ne s'applique pas aveuglément, dépend de son contexte
    • peuvent se combiner
    • est différent d'une bibliothèque
  • Vise à l'amélioration de l'efficacité, de la robustesse, du temps de développement, de la lisibilité du code

Avantages

  • Vocabulaire formalisé
  • Capitalisation de l'expérience
  • Niveau d'abstraction élevé
  • Complexité réduite
  • Temps de conception et développement réduit
  • Guide/catalogue de solutions
  • Aident à respecter les 5 principes SOLID

Inconvénients

  • Synthèse nécessaire :
    • Comment reconnaître une situation où un pattern s'applique ?
  • Apprentissage :
    • Catalogue volumineux : plus de 150 patrons répertoriés
    • Différents niveaux : des patrons de patrons
  • Adaptation du patron à son contexte

Le “Gang of Four”

gangoffour

1995

Patrons du GoF

Créationnels
Concernent le processus d'instanciation, d'initialisation et de configuration des classes et des objets
Structuraux
Concernent l'organisation des classes et des objets dans le programme, la manière dont ils sont connectés, composés pour obtenir des structures plus complexes
Comportementaux
Concernent les interactions dynamiques des classes et des objets, leurs collaborations
Concernent les algorithmes et la répartition des responsabilités entre les objets

Patrons du GoF

Créationnels (5) Structurels (7) Comportementaux (11)
Abstract Factory Adapter Chain of Responsibility
Builder Bridge Command
Factory Method Composite Interpreter
Prototype Decorator Iterator
Singleton Façade Mediator
Flyweight Memento
Proxy Observer
State
Strategy
Template Method
Visitor

Creational Patterns : principes généraux

Permettent des mécanismes efficaces de création d'objets, ce qui augmente la flexibilité et la réutilisation du code

Permettent dynamiquement ou statiquement de préciser les paramètres de la création : QUOI (l'objet), QUI (l'acteur), COMMENT (la manière) et QUAND (le moment)

Notamment les fabriques : quand plusieurs classes disponibles mais qu'on ne saura qu'au runtime laquelle et selon certaines conditions on doit instancier

Creational Patterns (1/2)

“Simple factory” (non GoF)
Cache les détails de la création dans une méthode qui retourne l'instance créée selon un paramètre (switch/case avec des new)
A modifier en cas d'ajouts d'objets
Factory Method
Une interface pour créer un objet, mais des sous-classes choisissent la classe à instancier : une méthode de création abstraite redéfinie dans des classes filles pour chaque type de produits, eux-mêmes hiérarchisés
En plus, permet de contrôler l'algorithme de création et la gestion de l'objet créé
Abstract Factory
Permet d’instancier des familles de produits dépendant les uns des autres sans avoir à préciser leur type concret
Ex : “si le produit est un A, alors c'est le service SA qui le gère ; si c'est un B, alors c'est SB”
Une fabrique abstraite avec une méthode de création par produit. Une fabrique concrète par famille.

Creational Patterns (2/2)

Builder
Pour la création d'objets complexes dont les différentes parties doivent être créées suivant un certain ordre ou algorithme spécifique
Peut remplacer un constructeur avec de nombreux et optionnels paramètres
Prototype
Permet de produire de nouveaux objets en clonant des objets existants sans compromettre leurs caractéristiques internes
Singleton
Permet d'assurer qu'une classe possède une seule instance et en fournir un point d'accès global

Structural Patterns : principes généraux

Permettent la construction de hiérarchies de classes et des relations entre les différentes classes simples et efficaces, ce qui facilite l'évolution de l'application

Structural Patterns (1/2)

Adapter
Permet à des objets ayant des interfaces incompatibles de travailler ensemble
Convertit l'interface d'une classe en une autre interface que les clients attendent
Bridge
Permet de diviser une classe massive ou un ensemble de classes étroitement liées en deux hiérarchies distinctes, l'abstraction et l'implémentation, qui peuvent être développées indépendamment l'une de l'autre.
Composite
Compose des objets dans des structures arborescentes et permet aux clients de travailler avec ces structures comme s'il s'agissait d'objets individuels

Structural Patterns (2/2)

Decorator
Permet d'attacher dynamiquement de nouveaux comportements aux objets en les plaçant à l'intérieur d'objets enveloppe qui contiennent ces comportements
Alternative souple à l'héritage pour étendre les fonctionnalités
Facade
Fournit une interface unifiée et plus simple à un système complexe de classes, bibliothèque ou framework
Définit une interface de haut niveau qui rend le sous-système plus facile à utiliser
Flyweight
Permet de partager les parties communes entre plusieurs objets, et ainsi gagner de l'espace mémoire
Proxy
Fournit un substitut ou un conteneur pour un autre objet afin d'en contrôler l'accès.

Behavioural Patterns : principes généraux

Permettent la communication, la distribution efficace et sûre des comportements entre les objets

Behavioural Patterns (1/4)

Chain of Responsibility
Évite de coupler l'expéditeur d'une requête à son destinataire en donnant à plus d'un objet une chance de traiter la demande
Enchaîne les récepteurs et fait passer la requête le long de la chaîne jusqu'à ce qu'un objet la traite.
Command
Permet d'encapsuler une requête en objet indépendant, qui peut être utilisé pour paramétrer des objets avec différentes requêtes, des files d'attente ou des requêtes de log
Permet des opérations annulables
Interpreter
Spécifie comment évaluer les phrases dans un langage

Behavioural Patterns (2/4)

Iterator
Fournit un moyen d'accéder séquentiellement aux éléments d'un agrégat sans exposer sa représentation sous-jacente
Mediator
Définit un objet qui encapsule comment un ensemble d'objets interagit
Favorise un couplage lâche en empêchant les objets de se référer explicitement, et permet de modifier leur interaction de manière indépendante
Memento
Permet de capturer et externaliser l'état interne d'un objet sans exposer sa structure afin qu'il puisse être restauré ultérieurement

Behavioural Patterns (3/4)

Observer
Définit une dépendance d‘un à plusieurs entre des objets afin que lorsqu'un objet change d’état, tous ses dépendants sont notifiés et mis à jour automatiquement
State
Autorise un objet à modifier son comportement lorsque son état interne change
L'objet semblera changer de classe
Strategy
Définit une famille d'algorithmes, les encapsule chacun et les rend interchangeables
Permet à l'algorithme de varier indépendamment des clients qui l'utilisent

Behavioural Patterns (4/4)

Template Method
Définit le squelette d'un algorithme dans une opération, reportant certaines étapes vers des sous-classes
Permet aux sous-classes de redéfinir certaines étapes de l'algorithme sans modifier sa structure
Visitor
Permet de définir une nouvelle opération sans modifier les classes des objets sur lesquels elle fonctionne

Exemple d'Architectural Pattern

Model-View-Controller

Principe MVC

Séparation claire entre données métier, présentation et traitements

A la base de nombreux frameworks, sous des formes diverses (adaptations)

MVC

Composants

Modèle
Couche métier
Gestion des données du programme et de leurs traitement
Comportement de l'application
Vue
Interface (graphique le plus souvent) avec l'utilisateur
Présentation de l'état du modèle
Gestion des requêtes utilisateurs
Contrôleur
Gestion des événements
Modification du modèle sur demande de l'utilisateur

Pour un modèle donné, plusieurs vues et contrôleurs possibles

Exemple Java

Pattern Observer + librairie graphique Swing

  • Modèle
    • est observable : extends java.util.Observable
    • Après chaque changement d'état, appelle setChanged () et notifyObservers ()
  • Vue
    • observe le Modèle : implements java.util.Observer
    • est ou contient une java.awt.Frame
    • contient des panels, boutons, textes…
    • possède une méthode void update(Observable obs, Object obj) appelée lors de la notification

Exemple Java

  • Controleur
    • est un listener : implements java.awt.event.ActionListener
    • connaît le modèle et la vue (attributs)
    • peut effectuer une action (actionPerformed(java.awt.event.ActionEvent e)) qui agit sur le modèle via ses méthodes
  • Un composant principal fait le lien entre M, V et C
    • instancie le modèle, la vue et le contrôleur
    • ajoute la vue comme observer du modèle
    • ajoute le controleur comme listener d'un élément adéquat de la vue

Exemple Java

MVCex

Exercices

Problème : Traitement d'informations de sources différentes

Votre programme doit lire des informations à partir de deux sources de données possibles, par ex. un fichier CSV et une base de données. Il doit ensuite traiter ces données de la bonne manière, et enfin générer des résultats en tant qu'autres fichiers CSV. Trois étapes sont impliquées.

  • Lire les données provenant de la source de données correspondante
  • Traiter les données selon la source
  • Ecrire la sortie dans les fichiers CSV

Proposez une architecture (sous forme de diagramme de classe).

Problème : objet unique

Proposez une solution qui assure qu'une classe ne sera instanciée qu'une fois (ex. game manager)

Problème : notifications

On souhaite proposer une solution aux clients d'une boutique en ligne pour les notifier automatiquement dès qu'un produit qui les intéresse devient disponible. Proposez une architecture.

Problème : création de points

On souhaite ajouter dans la classe Point2D un 2ème constructeur qui prend 2 coordonnées polaires (double, double), alors qu'on avait déjà Point2D(double x, double y). Est-ce possible ? Proposez une solution

Problème : création d'unités

On suppose qu'on dispose d'une hiérarchie d'Unités concrètes (Soldier, Healer, Tank…). Dans 2 modules clients (ex. UI et Network) on veut pouvoir instancier à la volée différentes unités en utilisant leur “type”. On ne veut pas avoir à modifier les clients lorsqu'il y aura de nouvelles unités. Proposez une solution.

Problème : un peu d'action

On veut maintenant que nos unités Soldier, Healer, Tank et les prochaines que l'on imaginera puissent effectuer une action d'attaque selon les régles imaginées par les game designers : normal shoot, debuff shoot, arrow shoot, no shoot…

Cette action doit pouvoir changer selon le type d'unité, mais aussi selon les instances d'un même type, voire même selon le contexte pour une instance donnée.

Proposez une solution.