Introduction aux design patterns

Qu’est-ce qu’un design pattern

  • Définition :

    C’est une solution éprouvée

    ... à un problème de conception logicielle récurrent

    ... proposée sous forme de fragment d'architecture objet.

  • Synonymes en français :

    patron de conception, modèle de conception, motif de conception

Historique

design pattern
  • Concept proposé par un architecte (Christopher Alexander) dans les années 70 pour apporter des solution à des problèmes courants dans le bâtiment (solidité, structure, étanchéité…​)

  • Application du concept à l’ingénierie logicielle dans les années 80

  • Large diffusion en 1994 grâce au livre “Design patterns: elements of reusable object-oriented software”

    • Auteurs : “La bandes des 4” ou Gang of Four souvent abrégé en GoF

    • Contenu : 23 architectures objet constituant des propositions de solution à autant de situations courantes.

Pourquoi utiliser les design pattern

  • Pour accélérer le processus de développement en fournissant des solutions de développement éprouvées.

  • Pour anticiper des problématiques qui peuvent ne devenir visibles que plus tard dans la mise en œuvre.

  • Pour améliorer la lisibilité du code en fournissant une standardisation.

Classification

3 familles de design pattern selon la problématique à traiter

  1. Comment structurer son code pour faciliter l’interaction entre les objets ?

    ⇒ Patrons de structure (structural patterns)

    Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy

  2. Comment faire communiquer des objets entre eux ?

    ⇒ Patrons de comportement (behavioral patterns)

    Strategy, Chain of responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Template Method, Visitor

  3. Comment créer ou configurer des objets pour une utilisation adaptée au contexte ?

    ⇒ Patrons de création (creational patterns)

    Singleton, Abstract Factory, Builder, Factory Method, Prototype

Étude du design pattern Adapter

Généralités

  • Objectif :

    Adapter l’interface d’une ou plusieurs classes afin de les rendre compatibles avec ce qu’attend l’utilisateur de ces classes

  • Illustration :

    adapter

Étude de cas

  • Mise en situation :

On désire mettre en œuvre un ensemble de capteurs de températures pour surveiller un local technique.

2 types de capteurs sont disponibles.

Chacun des capteurs dispose d’une librairie C++ pour permettre son exploitation : fichier d’entête .h + librairie statique sous forme binaire (libfoosensor.a pour le capteur FooSensor, libbarsensor.a pour le capteur BarSensor). Nous n’avons donc pas accès au code source de ces librairies.

adaptee
  • Problématique :

    Les 2 types de capteurs délivrant — via les méthodes getTemperature() et readTemp() de leur librairies respectives — une température dans 2 unités différentes (°C et °F), comment utiliser ces 2 types de capteur de manière uniforme ? (c’est-à-dire n’utiliser qu’une seule méthode pour acquérir une T° exprimée en °C quel que soit le type de capteur)

  • Solution : le patron Adapter

    adapter
  • Application à notre exemple

    adapter solution

On va créer une interface commune aux 2 capteurs (→ classe CapteurTemperature) puis 2 classes intermédiaires (→ FooAdapter et BarAdapter) qui vont convertir les valeurs retournées par les méthodes présentes dans chacune des librairies de façon à se conformer à ce qui est défini dans l’interface à savoir retourner une température en °C.

qdemoadapter

Ce code source est à compiler sous Windows. Adapter les fichier .pro pour les compiler sur une autre plateforme

Étude du patron Strategy

Généralités

  • Objectif :

    Définir une famille de comportements/algorithmes indépendants qui répondent à la même interface et qui sont interchangeables dynamiquement depuis le client qui les utilise.

    Exemple : trier des nombres par ordre croissant avec plusieurs algorithmes (bubble sort, quick sort…​)

  • Illustration :

    strategy

Étude de cas

  • Mise en situation

    On désire faire une application qui supervise la vitesse du vent — relevée à l’Isle sur la Sorgue — en affichant sa vitesse en km/h et également son équivalent sur l’échelle de Beaufort link.

    La vitesse du vent en m/s nous est fournie par une API Web (OpenWeatherMap link ).

    L’affichage de la vitesse du vent dans l’IHM sera réactualisé toutes les 2 secondes.

  • Problématique

    Comment vérifier que l’application affiche la bonne vitesse de vent sur l’échelle de Beaufort en fonction de la vitesse du vent renvoyée par l’API Web sachant qu’on ne peut pas changer la force du vent à notre convenance.

  • Solution : le patron Strategy

    strategy

    On va coder notre application de sorte à ce qu’elle utilise soit la vitesse du vent réelle retournée par l’API Web soit celle retournée par un capteur de vent simulé.

    Le patron de conception Strategy sera mis en œuvre pour choisir depuis l’IHM de notre application (c’est-à-dire lors de l’exécution de l’application), le capteur de vent à utiliser (réel ou simulé).

    qdemostrategy
  • Application à notre exemple

    strategy solution

Pour que l’application fonctionne, fournir votre propre clé d’API OpenWeatherMap dans le fichier realwindspeedsensor.cpp de la démo.

m_nr.setUrl(QUrl("http://api.openweathermap.org/data/2.5/weather?q=L'Isle-sur-la-sorgue,fr&appid=<<VOTRE_CLE_D_API>>"));

Étude du patron Singleton

Généralités

  • Objectifs :

    1. assurer qu’il n’existe qu’une seule instance de la classe

    2. fournir un moyen d’obtenir cette instance unique

  • Illustration :

    singleton

Étude de cas

  • Mise en situation :

    On veut coder une classe qui permet de tenir un fichier journal (→ log) dans lequel différents composants d’une application peuvent — de manière optionnelle et à la demande — écrire des messages d’information ou d’erreur.

demo singleton
  • Problématique :

    1. Comment s’assurer qu’un seul journal sera créé/utilisé quel que soit le composant d’où émane la 1ière demande ?

    2. Comment s’assurer que le fichier journal sera fermé lorsque le dernier des composants à l’utiliser mettra fin à la journalisation ?

  • Solution : le patron Singleton

    singleton
  • Application à notre exemple

    singleton solution

demo

Autres cas d’utilisation du design pattern Singleton :

  • accès centralisé à une BDD

  • accès centralisé à du matériel (ex. : classe de gestion d’un bus I2C)

🞄  🞄  🞄