Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Fathi Bellahcene

.Net m'a tuer!

Design pattern Decorator (décorateur)

 

 

Très souvent, lorsque l’on souhaite ajouter des fonctionnalités à une classe on pense : héritage – et c’est un bon réflexe.

Mais - très souvent également- la solution n’est pas forcément adapté : on peut souhaiter ajouter plusieurs fonctionnalités à la même classe de manière dynamique (runtime) et non pas à l’écriture du programme (ajout de fonctionnalité statique) en choisissant les nouvelles fonctionnalités pour chaque instance et non pas pour la classe. Dans ces cas, on doit faire appel au pattern Decorator (pattern du GoF de type structure).

Prenons un exemple simple pour illustrer ce pattern trop peu utilisé dans notre écosystème.

Prenons, par exemple, la modélisation de glaces :

· il en existe plein de types :à l’eau, italienne, avec des boules,…

· et tous ces types de glace on en commun des gouts : chocolat, vanille, citron, etc…

On souhaite donc pouvoir avoir un modèle permettant d’avoir une glace Italienne au chocolat et à la vanille. On va donc pouvoir utiliser l’héritage avec par exemple : la classe Italienne (qui hérite de glace) et qui a comme propriété une liste de gouts

Sauf que si on ajoute des options tels que des amandes grillés dessus ou autre chose, on complexifie le modèle et surtout on risque de ne plus respecter le principe SOLID « open close principle ».

Voyons comme le pattern Decorator peut nous aider de manière élégante :

Dans ce pattern, on va identifier deux parties de l’arbre d’éritage:

1. la partie classique ou l’on va retrouver nos classes Glace (abstraite) GlaceItalienne et GlaceALeau.

2. La partie liée aux ajouts de fonctionnalités avec

a. une autre classe abstraite GlaceDecorator qui servira de base pour tous les décorator (ie fonctionnalités)

b. les décorateurs concrets : GoutVanille & GoutChocolat qui en héritent.

clip_image002

Pour le code, on va juste compléter la description de la glace :

public abstract class Glace
    {
        public virtual string Description
        {
            get
            {
                return "Glace virtuelle";
            }
        }
    }

    public class GlaceItalienne : Glace
    {
        public override string Description
        {
            get
            {
                return "glace italienne";
            }
        }
    }

    public class GlaceALeau : Glace
    {
        public override string Description
        {
            get
            {
                return "glace a l'eau";
            }
        }
    }

    public abstract class GlaceDecorator : Glace
    {
        protected Glace _glace;

        public override string Description
        {
            get
            {
                return _glace.Description;
            }
        }

    }

    public class GoutChocolat : GlaceDecorator
    {
        public GoutChocolat(Glace glace)
        {
            _glace = glace;
        }

        public override string Description
        {
            get
            {
                return _glace.Description + " avec du chocolat ";
            }
        }

    }

    public class GoutVanille : GlaceDecorator
    {

        public GoutVanille(Glace glace)
        {
            _glace = glace;
        }

        public override string Description
        {

            get
            {
                return _glace.Description + " avec de la vanille ";
            }
        }
    }

Et donc, à l’utilisation j’ai juste a instancier une glace italienne et ajouter mes options  vanille et chocolat par exemple :

static void Main(string[] args) 
        { 
            Glace maglace = new GlaceItalienne(); 
            maglace = new GoutChocolat(maglace); 
            maglace = new GoutVanille(maglace); 
            Console.WriteLine(maglace.Description); 
            Console.ReadKey(); 
        }

J’ai le résultat suivant à la console :

clip_image004

De cette manière, avec un arbre d’héritage peu complexe, on a la possibilité d’avoir des compositions dynamiques très complexes tout en respectant le principe « open close ».

Un des avantage de ce pattern est l’aspect dynamique et optionnel des fonctionnalités que l’on ajoute et, mine de rien, si on le met en place suffisamment tôt lorsque l’on développe la solution reste simple et élégante.

Par contre, contrairement à l’héritage nous n’avons pas accès aux propriétés et méthodes privés de l’objet que l’on décore.

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: jeudi 26 septembre 2013 15:17 par fathi

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01