Je lisais un article de programmation et il mentionnait le modèle Decorator. Je programme depuis un certain temps, mais sans aucune sorte d'éducation ou de formation formelle, mais j'essaie d'en apprendre davantage sur les modèles standard et autres.
J'ai donc recherché le décorateur et trouvé un article Wikipedia à ce sujet. Je comprends maintenant le concept du motif Decorator, mais j'étais un peu confus par ce passage:
Par exemple, considérons une fenêtre dans un système de fenêtrage. Pour permettre le défilement du contenu de la fenêtre, nous pouvons souhaiter lui ajouter des barres de défilement horizontales ou verticales, selon le cas. Supposons que les fenêtres sont représentées par des instances de la classe Window et supposons que cette classe n'a aucune fonctionnalité pour ajouter des barres de défilement. Nous pourrions créer une sous-classe ScrollingWindow qui les fournit, ou nous pourrions créer un ScrollingWindowDecorator qui ajoute cette fonctionnalité aux objets Window existants. À ce stade, l'une ou l'autre solution conviendrait.
Supposons maintenant que nous souhaitons également pouvoir ajouter des bordures à nos fenêtres. Encore une fois, notre classe Window d'origine ne prend pas en charge. La sous-classe ScrollingWindow pose maintenant un problème, car elle a effectivement créé un nouveau type de fenêtre. Si nous souhaitons ajouter un support de bordure à toutes les fenêtres, nous devons créer des sous-classes WindowWithBorder et ScrollingWindowWithBorder. De toute évidence, ce problème s'aggrave avec chaque nouvelle fonctionnalité à ajouter. Pour la solution de décoration, nous créons simplement un nouveau BorderedWindowDecorator - au moment de l'exécution, nous pouvons décorer les fenêtres existantes avec le ScrollingWindowDecorator ou le BorderedWindowDecorator ou les deux, comme bon nous semble.
OK, quand ils disent d'ajouter des bordures à toutes les fenêtres, pourquoi ne pas simplement ajouter des fonctionnalités dans la classe Window d'origine pour permettre l'option? Pour moi, le sous-classement consiste simplement à ajouter des fonctionnalités spécifiques à une classe ou à remplacer une méthode de classe. Si j'avais besoin d'ajouter des fonctionnalités à tous les objets existants, pourquoi ne modifierais-je pas simplement la superclasse pour le faire?
Il y avait une autre ligne dans l'article:
Le motif décorateur est une alternative au sous-classement. Le sous-classement ajoute un comportement au moment de la compilation et la modification affecte toutes les instances de la classe d'origine; la décoration peut fournir un nouveau comportement au moment de l'exécution pour des objets individuels.
Je n'arrive pas là où ils disent "... le changement affecte toutes les instances de la classe d'origine" - comment le sous-classement change-t-il la classe parente? N'est-ce pas là tout l'intérêt du sous-classement?
Je vais supposer que l'article, comme de nombreux Wiki, n'est tout simplement pas écrit clairement. Je peux voir l'utilité du décorateur dans cette dernière ligne - "... fournir un nouveau comportement au moment de l'exécution pour les objets individuels."
Sans avoir lu ce modèle, si j'avais besoin de changer le comportement au moment de l'exécution pour des objets individuels, j'aurais probablement intégré certaines méthodes dans la super ou sous-classe pour activer / désactiver ledit comportement. S'il vous plaît, aidez-moi à vraiment comprendre l'utilité du décorateur et pourquoi ma pensée de débutant est défectueuse?
Réponses:
Le modèle de décorateur est celui qui privilégie la composition plutôt que l'héritage [un autre paradigme de POO qui est utile pour en savoir plus]
Le principal avantage du motif décorateur - par rapport au sous-classement est de permettre plus d'options de mix & match. Si vous avez, par exemple, 10 comportements différents qu'une fenêtre peut avoir, cela signifie - avec le sous-classement - que vous devez créer chaque combinaison différente, ce qui inclura également inévitablement beaucoup de réutilisation de code.
Cependant, que se passe-t-il lorsque vous décidez d'ajouter un nouveau comportement?
Avec le décorateur, vous ajoutez simplement une nouvelle classe qui décrit ce comportement, et c'est tout - le modèle vous permet de le déposer efficacement sans aucune modification dans le reste du code.
Avec la sous-classification, vous avez un cauchemar entre vos mains.
Une question que vous avez posée était "comment le sous-classement change-t-il la classe parente?" Ce n'est pas que cela change la classe parente; quand il dit une instance, cela signifie tout objet que vous avez «instancié» [si vous utilisez Java ou C #, par exemple, en utilisant la
new
commande]. Ce à quoi il fait référence, c'est que lorsque vous ajoutez ces modifications à une classe, vous n'avez pas le choix pour que cette modification soit là, même si vous n'en avez pas réellement besoin.Alternativement, vous pouvez mettre toutes ses fonctionnalités dans une seule classe avec elle activée / désactivée via des drapeaux ... mais cela se termine par une seule classe qui devient de plus en plus grande à mesure que votre projet se développe.
Il n'est pas inhabituel de commencer votre projet de cette façon et de refaçonner un modèle de décorateur une fois que vous avez atteint une masse critique efficace.
Un point intéressant à souligner: vous pouvez ajouter plusieurs fois la même fonctionnalité; Ainsi, vous pourriez, par exemple, avoir une fenêtre avec double, triple ou tout autre montant ou bordures selon vos besoins.
Le point principal du modèle est d'activer les modifications au moment de l'exécution: vous ne savez peut-être pas à quoi ressemble la fenêtre jusqu'à ce que le programme soit en cours d'exécution, ce qui vous permet de la modifier facilement. Certes, cela peut être fait via le sous-classement, mais pas aussi bien.
Et enfin, il permet d'ajouter des fonctionnalités à des classes que vous ne pourrez peut-être pas modifier - par exemple dans des classes scellées / finales ou fournies par d'autres API
la source
Considérez les possibilités d'ajouter des barres de défilement et des bordures avec le sous-classement. Si vous voulez chaque possibilité, vous obtenez quatre classes (Python):
Maintenant, dans
WindowWithScrollBarAndBorder.draw()
, la fenêtre est dessinée deux fois, et la deuxième fois, elle peut ou non remplacer la barre de défilement déjà dessinée, selon l'implémentation. Votre code dérivé est donc étroitement lié à l'implémentation d'une autre classe, et vous devez vous en soucier chaque fois que vous modifiez leWindow
comportement de la classe. Une solution serait de copier-coller le code des super classes dans les classes dérivées et de l'ajuster aux besoins des classes dérivées, mais chaque changement dans une super classe doit être recopié et ajusté à nouveau, donc les classes dérivées sont à nouveau étroitement couplé à la classe de base (via la nécessité de copier-coller-ajuster). Un autre problème est que si vous avez besoin d'une autre propriété qu'une fenêtre peut avoir ou non, vous devez doubler chaque classe:Cela signifie que pour un ensemble de fonctionnalités mutuellement indépendantes f avec | f | étant le nombre de fonctionnalités, vous devez définir 2 ** | f | des classes, par exemple. si vous avez 10 fonctionnalités, vous obtenez 1024 classes étroitement coulped. Si vous utilisez le modèle de décorateur, chaque fonction a sa propre classe indépendante et faiblement couplée et vous n'avez que 1 + | f | (c'est 11 pour l'exemple ci-dessus).
la source
Je ne suis pas un expert de ce modèle particulier, mais comme je le vois, le modèle Decorator peut être appliqué à des classes que vous n'avez peut-être pas la possibilité de modifier ou de sous-classe (elles peuvent ne pas être votre code et être scellées, par exemple ). Dans votre exemple, que se passe-t-il si vous n'avez pas écrit la classe Window mais que vous la consommez simplement? Tant que la classe Window a une interface et que vous programmez contre cette interface, votre décorateur peut utiliser la même interface mais étendre les fonctionnalités.
L'exemple que vous mentionnez est en fait très bien couvert ici :
http://www.oodesign.com/decorator-pattern.html
la source