Mode Décorateur

Le patron Decorator permet d'ajouter de nouvelles fonctionnalités à un objet existant sans modifier sa structure. Ce type de patron de conception appartient aux patrons structurels et sert d'enveloppe pour une classe existante.

Le patron Decorator modifie dynamiquement le comportement d'un objet en enveloppant l'objet dans des classes de décorateurs.

Ce patron crée une classe de décorateur qui enveloppe la classe d'origine et fournit des fonctionnalités supplémentaires tout en préservant l'intégrité des signatures de méthodes de la classe.

Nous utilisons l'exemple suivant pour démontrer l'utilisation du patron Decorator. Ici, nous allons décorer une forme avec différentes couleurs sans modifier la classe de la forme.

summary

intention

Ajouter dynamiquement des responsabilités supplémentaires à un objet sans modifier sa structure. Le patron Decorator offre une alternative flexible à l'héritage pour étendre les fonctionnalités.

Principaux problèmes à résoudre

  • Éviter d'introduire des fonctionnalités statiques par héritage, en particulier lorsque le nombre de sous-classes augmente rapidement.
  • Permet d'ajouter ou de modifier dynamiquement les fonctionnalités d'un objet au moment de l'exécution.

Cas d'utilisation

  • Lorsque vous devez étendre les fonctionnalités d'une classe sans ajouter un grand nombre de sous-classes.
  • Lorsque vous devez ajouter ou révoquer dynamiquement les fonctionnalités d'un objet.

Approche d'implémentation

  • Définir l'interface du composantCréer une interface qui définit la norme pour les objets auxquels des responsabilités peuvent être ajoutées dynamiquement.
  • Créer des composants concretsDes classes concrètes qui implémentent cette interface, fournissant des fonctionnalités de base.
  • Créer un décorateur abstraitImplémente la même interface, détient une référence à une interface de composant et peut ajouter dynamiquement des fonctionnalités à tout moment.
  • Créer des décorateurs concretsÉtend le décorateur abstrait, en ajoutant des responsabilités supplémentaires.

Code clé

  • Interface de composantDéfinit la norme pour les objets pouvant être décorés.
  • Classe ConcreteComponentDes classes concrètes qui implémentent l'interface Component.
  • Classe abstraite DecoratorImplémente l'interface Component et contient une référence à une interface Component.
  • Classe ConcreteDecoratorÉtend la classe Decorator, en ajoutant des fonctionnalités supplémentaires.

Exemple d'application

  1. Les 72 transformations du Roi Singe: Sun Wukong (ConcreteComponent) acquiert de nouvelles capacités grâce à la transformation (Decorator).
  2. Peinture décorative encadrée: Une peinture (ConcreteComponent) peut améliorer son effet d'affichage en ajoutant du verre (ConcreteDecorator) et un cadre (ConcreteDecorator).

Avantages

  • Faible couplageLes classes décoratrices et les classes décorées peuvent changer indépendamment sans s'affecter mutuellement.
  • Flexibilité: peut ajouter ou retirer dynamiquement des fonctionnalités.
  • Remplacer l'héritageFournit un moyen d'étendre les fonctionnalités d'un objet en dehors de l'héritage.

Inconvénients

  • ComplexitéLa décoration multicouche peut augmenter la complexité du système.

Suggestions d'utilisation

  • Lorsque vous devez étendre dynamiquement des fonctionnalités, envisagez d'utiliser le patron Décorateur.
  • Gardez les interfaces des décorateurs et des composants concrets cohérentes pour garantir la flexibilité.

Notes

  • Le patron Décorateur peut remplacer l'héritage, mais il doit être utilisé avec prudence afin d'éviter une sur-décoration conduisant à une complexité du système.

Structure

Le patron Décorateur comprend les rôles principaux suivants :

  • Composant abstrait : définit l'interface commune ou la classe abstraite pour les objets d'origine et les objets décorateurs, et peut servir de classe parente ou d'interface pour les classes de composants concrets.
  • Composant concret : est l'objet d'origine qui est décoré, définissant l'objet auquel de nouvelles fonctionnalités doivent être ajoutées.
  • Décorateur abstrait : hérite du composant abstrait, contient un objet composant abstrait, définit la même interface que le composant abstrait et peut contenir d'autres objets décorateurs par composition.
  • Décorateur concret : implémente l'interface du décorateur abstrait et est responsable de l'ajout de nouvelles fonctionnalités au composant abstrait. Les décorateurs concrets effectuent généralement leurs propres opérations avant ou après l'appel des méthodes de l'objet d'origine.

Le patron Decorator permet une amélioration fonctionnelle multi-niveaux par emboîtement de plusieurs objets décorateurs. Chaque classe de décorateur concrète peut ajouter sélectivement de nouvelles fonctionnalités tout en maintenant la cohérence de l'interface de l'objet.

Implémentation

Nous allons créer uneShapeInterface et une implémentationShapeLa classe d'entité de l'interface. Ensuite, nous créons une implémentation quiShapeClasse décoratrice abstraite pour l'interface.ShapeDecorator, etShapeobjet comme sa variable d'instance.

RedShapeDecoratorimplémenteShapeDecoratorclasse d'entité.

DecoratorPatternDemoUtilisation de la classeRedShapeDecoratorPour décorerShapeObjet.

<img decoding="async" src="../wp-content/uploads/2014/08/20210420-decorator-1-decorator-decorator.svg" alt="Diagramme UML du mode Decorator" />

Étape 1

Créez une interface :

Shape.java

public interface Shape { void draw(); }

Étape 2

Créez une classe d'entité qui implémente l'interface.

Rectangle.java

public class Rectangle implements Shape { @Override public void draw() { System.out.println("Shape: Rectangle"); } }

Circle.java

public class Circle implements Shape { @Override public void draw() { System.out.println("Shape: Circle"); } }

Étape 3

Créez une implémentationShapeClasse décoratrice abstraite pour l'interface.

ShapeDecorator.java

public abstract class ShapeDecorator implements Shape { protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){ this.decoratedShape = decoratedShape; } public void draw(){ decoratedShape.draw(); } }

Étape 4

Créer une extensionShapeDecoratorClasse de décorateur d'entité pour la classe.

RedShapeDecorator.java

public class RedShapeDecorator extends ShapeDecorator { public RedShapeDecorator(Shape decoratedShape) { super(decoratedShape); } @Override public void draw() { decoratedShape.draw(); setRedBorder(decoratedShape); } private void setRedBorder(Shape decoratedShape){ System.out.println("Couleur de la bordure: Rouge"); } }

Étape 5

UtilisationRedShapeDecoratorpour décorerShapeObject.

DecoratorPatternDemo.java

public class DecoratorPatternDemo { public static void main(String[] args) { Shape circle = new Circle(); ShapeDecorator redCircle = new RedShapeDecorator(new Circle()); ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle()); //Shape redCircle = new RedShapeDecorator(new Circle()); //Shape redRectangle = new RedShapeDecorator(new Rectangle()); System.out.println("Cercle avec bordure normale"); circle.draw(); System.out.println("\nCercle avec bordure rouge"); redCircle.draw(); System.out.println("\nRectangle à bordure rouge"); redRectangle.draw(); } }

Étape 6

Exécutez le programme, affichez le résultat :

Circle with normal border
Shape: Circle

Circle of red border
Shape: Circle
Border Color: Red

Rectangle of red border
Shape: Rectangle
Border Color: Red
autres extensions