Cours design patterns - design patterns - télécharger pdf

Examen ACSI : Design Patterns

Introduction

•Objectifs

–Modularité : facilité de gestion grâce à la technologie objet

–Cohésion : degré de relation fonctionnelle entre les tâches d’un module. Une forte cohésion est une bonne qualité.

–Couplage : degré d’interaction entre les modules. Un couplage « lâche » est une bonne qualité.

–Réutilisabilité : bibliothèques, frameworks (cadre de travail)

Cohésion : « mauvais » exemple

La classe GameBoard ci-dessous illustre une mauvaise cohésion : elle gère à la fois les règles du jeu et l’affichage.

public class GameBoard {
    public GamePiece[][] getState() { ... } // Méthode copiant la grille dans un tableau temporaire
    public Player isWinner() { ... } // Vérifie l’état du jeu pour déterminer un gagnant (renvoie null si aucun gagnant)
    public boolean isTie() { ... } // Retourne true si aucun déplacement possible, false sinon
    public void display() { ... } // Affiche le contenu du jeu, y compris les espaces vides pour les références nulles
}

Cohésion : « bon » exemple

Pour améliorer la cohésion, la classe GameBoard se concentre uniquement sur les règles du jeu, tandis que BoardDisplay gère l’affichage.

public class GameBoard {
    public GamePiece[][] getState() { ... }
    public Player isWinner() { ... }
    public boolean isTie() { ... }
}

public class BoardDisplay {
    public void displayBoard(GameBoard gb) { ... } // Affiche le contenu du jeu, y compris les espaces vides pour les références nulles
}

Couplage : exemple

Un couplage fort entre le client et la méthode initArray est illustré par le paramètre nStudents.

void initArray(int[] iGradeArray, int nStudents) {
    int i;
    for (i = 0; i < nStudents; i++) {
        iGradeArray[i] = 0;
    }
}

Un couplage faible, plus fiable, utilise l’attribut length de l’objet iGradeArray.

void initArray(int[] iGradeArray) {
    int i;
    for (i = 0; i < iGradeArray.length; i++) {
        iGradeArray[i] = 0;
    }
}

Principes de conception

•Programmer une interface plutôt qu’une implémentation

•Utiliser des classes abstraites (interfaces en Java) pour définir des interfaces communes à un ensemble de classes

•Déclarer les paramètres comme instances de la classe abstraite plutôt que comme instances de classes particulières

Ainsi : les classes clientes ou les objets sont indépendants des classes des objets qu’ils utilisent tant que les objets respectent l’interface attendue.

•Préférer la composition d’objets à l’héritage de classes

Ainsi : le comportement peut changer en cours d’exécution, les classes sont plus focalisées sur une tâche et les dépendances d’implémentation sont réduites.

Définition : Pattern

Un patron décrit à la fois un problème récurrent dans un environnement et une solution architecturale réutilisable sans adaptation répétée.

Il permet de décrire des solutions types à des problèmes communs dans des situations similaires.

Définition : Design Pattern

•Coad (1992) : une abstraction d’un doublet, triplet ou ensemble de classes réutilisable pour le développement d’applications.

•Appleton (1997) : une règle tripartite exprimant une relation entre un contexte, un problème récurrent et une solution logicielle.

•Aarsten (1996) : un groupe d’objets coopérants liés par des relations et des règles exprimant les liens entre contexte, problème et solution.

Les design patterns sont des solutions logiques documentées indépendamment d’un langage de programmation donné.

Définition : Design Pattern (suite)

•Documentation d’une expérience de conception éprouvée

•Identification et spécification d’abstractions au-dessus du niveau des classes simples

•Vocabulaire commun facilitant la compréhension des principes de conception

•Moyen de documentation des logiciels

•Aide à la construction de logiciels complexes et hétérogènes répondant à des propriétés précises

Historique

Les design patterns ont évolué à travers plusieurs conférences et publications :

–PLoP (1994)

–Montebello Design Patterns (1994)

–Gamma, Helm, Johnson, Vlissides (1995)

–EuroPLoP (1996)

–OOPSLA (1987, 1991, 1992)

–Coad (1995)

–Coplien et Schmidt (1995)

–Buschmann (1996)

–Fowler (1997)

–ChiliPLoP (1998)

Catégories de Design 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, avec une portée plus limitée que les « architectural patterns »

•Idioms ou Coding Patterns : solutions liées à un langage particulier

•Anti-Patterns : mauvaises solutions ou comment éviter une mauvaise solution

•Organizational Patterns : schémas d’organisation autour du développement logiciel (humains)

Catégories de Design Patterns (détails)

•Création : description de la manière dont les objets sont créés, initialisés et configurés. Isolation du code de création pour rendre l’application indépendante.

•Structure : description de la composition des classes et objets pour former des structures plus importantes, tout en assurant leur indépendance face aux évolutions futures.

•Comportement : description des interactions entre objets et gestion des dynamiques entre classes.

Portée des Design Patterns

•Portée de Classe : relations entre classes et sous-classes, réutilisation par héritage.

•Portée d’Instance : relations entre objets, réutilisation par composition.

Design Patterns du GoF

•Création : Factory Method, Abstract Factory, Builder, Prototype, Singleton

•Structure : Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy

•Comportement : Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor

Présentation d’un Design Pattern

•Nom du pattern : utilisé pour décrire le pattern, ses solutions et les conséquences en un ou deux mots.

•Problème : description des conditions d’application, explication du contexte et du problème.

•Solution : éléments (objets, relations, responsabilités, collaborations) permettant de concevoir la solution, avec une vision statique et dynamique.

•Conséquences : résultats positifs et négatifs de l’application du pattern sur le système.

Design Patterns de création

•Objectif : rendre le système indépendant de la manière dont les objets sont créés, composés et représentés.

•Encapsulation de la connaissance des classes concrètes.

•Préciser dynamiquement ou statiquement : QUOI (l’objet), QUI (l’acteur), COMMENT (la manière) et QUAND (le moment) de la création.

•Deux types de motifs :

–Motifs de création de classe (héritage) : Factory Method

–Motifs de création d’objets (délégation) : Abstract Factory, Builder, Prototype

Exemple : Labyrinthe (Factory Method)

La classe MazeGame utilise des méthodes virtuelles pour créer les composants du labyrinthe, permettant une personnalisation par héritage.

class MazeGame {
    void Play() { ... }
    public Maze createMaze() {
        Maze aMaze = makeMaze();
        Room r1 = makeRoom(1);
        Room r2 = makeRoom(2);
        Door theDoor = makeDoor(r1, r2);
        aMaze.addRoom(r1);
        aMaze.addRoom(r2);
        r1.setSide(North, makeWall());
        r1.setSide(East, theDoor);
        r1.setSide(South, makeWall());
        r1.setSide(West, makeWall());
        r2.setSide(North, makeWall());
        r2.setSide(East, makeWall());
        r2.setSide(South, makeWall());
        r2.setSide(West, theDoor);
        return aMaze;
    }
}

class BombedMazeGame extends MazeGame {
    public Wall makeWall() {
        return new BombedWall();
    }
    public Room makeRoom(int i) {
        return new RoomWithABomb(i);
    }
}

Abstract Factory

•Problème : travailler avec des familles de produits tout en restant indépendant du type de ces produits.

•Conséquences :

+Séparation des classes concrètes et des classes clientes

+Facilite l’échange de familles de produits

+Favorise la cohérence entre les produits

+Processus de création isolé dans une classe

–Mise en place de nouveaux produits dans l’Abstract Factory non aisée.

•Exemple : java.awt.Toolkit

Exemple : Labyrinthe (Abstract Factory)

La classe MazeGame utilise une interface MazeFactory pour créer les composants du labyrinthe, permettant une flexibilité accrue.

class MazeGame {
    void Play() { ... }
    public Maze createMaze(MazeFactory f) {
        Maze aMaze = f.makeMaze();
        Room r1 = f.makeRoom(1);
        Room r2 = f.makeRoom(2);
        Door theDoor = f.makeDoor(r1, r2);
        aMaze.addRoom(r1);
        aMaze.addRoom(r2);
        r1.setSide(North, f.makeWall());
        r1.setSide(East, theDoor);
        r1.setSide(South, f.makeWall());
        r1.setSide(West, f.makeWall());
        r2.setSide(North, f.makeWall());
        r2.setSide(East, f.makeWall());
        r2.setSide(South, f.makeWall());
        r2.setSide(West, theDoor);
        return aMaze;
    }
}

class BombedMazeFactory extends MazeFactory {
    public Wall makeWall() {
        return new BombedWall();
    }
    public Room makeRoom(int i) {
        return new RoomWithABomb(i);
    }
}

Builder

•Problème : algorithme de création indépendant des constituants de l’objet ou différentes représentations possibles.

•Conséquences :

+Variation possible de la représentation interne d’un produit

+Isolation du code de construction et du reste de l’application

+Meilleur contrôle du processus de construction

Prototype

•Problème : système indépendant de la création des produits, évitant les hiérarchies de Factory.

•Conséquences : mêmes avantages que Factory et Builder.

•Exemple : java.lang.Cloneable

Singleton

•Problème : garantir une seule instance d’une classe et y accéder facilement.

•Solution : une seule classe contrôle la création de l’instance.

•Conséquences : l’unicité est contrôlée par la classe, mais le pattern peut être étendu pour gérer plusieurs instances.

Exemple : Singleton

class Singleton {
    private static Singleton instance = null;
    private Singleton() { ... }
    public static Singleton getInstance() {
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
}

class Program {
    public void aMethod() {
        Singleton X = Singleton.getInstance();
    }
}

Résumé : Design Patterns de création

•Factory Method : choisit et retourne une instance parmi plusieurs classes similaires, selon une donnée fournie.

•Abstract Factory : retourne un groupe de classes (famille de produits) tout en isolant les classes concrètes.

•Builder : assemble des objets pour construire un nouvel objet complexe, souvent en utilisant une Factory pour le choix des composants.

•Prototype : copie ou clone une classe existante pour éviter une création coûteuse.

•Singleton : garantit une seule instance d’un objet et permet un accès global.

Design Patterns de structure

•Abstraction de la composition des classes et objets pour former des structures plus complexes.

•Deux types de motifs :

–Motifs de structure de classes : utilisation de l’héritage pour composer des interfaces ou implémentations (ex : Adapter).

–Motifs de structure d’objets : composition d’objets pour ajouter des fonctionnalités ou niveaux d’indirection (ex : Adapter d’objet, Bridge, Facade, Proxy) ou organiser récursivement (ex : Composite).

Adapter

•Problème : utilisation d’une classe existante dont l’interface ne convient pas ou adaptation de plusieurs sous-classes.

•Conséquences :

–Adapter de classe : une seule classe introduite, pas d’indirection nécessaire.

–Adapter d’objet : peut fonctionner avec plusieurs classes adaptées, mais difficile à étendre pour redéfinir des comportements.

FAQ

Qu’est-ce qu’un design pattern ?

Un design pattern est une solution éprouvée à un problème récurrent en conception logicielle, documentée de manière à être réutilisée sans modification dans différents contextes.

Quelle est la différence entre Factory Method et Abstract Factory ?

La Factory Method crée une seule classe, tandis que l’Abstract Factory crée une famille de classes liées, offrant une flexibilité accrue pour les produits.

À quel moment utiliser le pattern Singleton ?

Le pattern Singleton est utile lorsqu’une classe doit avoir une seule instance globale, comme un gestionnaire de configuration ou un service unique dans une application.

Cela peut vous intéresser :

Partagez vos remarques, questions , propositions d'amélioration ou d'autres cours à ajouter dans notre site

Enregistrer un commentaire (0)
Plus récente Plus ancienne