Je peux résoudre le problème de l'ajout de fonctionnalités en ajoutant des sous-classes, alors pourquoi devrais-je utiliser un motif de décoration, quel est le véritable avantage du motif de décoration?
de Motif décorateur sur wikipedia
Le motif décorateur peut être utilisé pour permettre d'étendre (décorer) la fonctionnalité d'un certain objet lors de l'exécution .
L'intérêt du motif de décoration est d'ajouter dynamiquement un comportement/des fonctionnalités supplémentaires, ce qui n'est bien sûr pas possible au moment de la conception.
du même article:
Le motif décorateur est une alternative au sous-classement. Le sous-classement ajoute un comportement au moment de la compilation, et le changement 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.
Un exemple du GoF:
Supposons que vous ayez une classe TextView. Ensuite, à un certain endroit, vous voulez une vue de texte défilée, donc vous sous-classe TextView et créez la classe ScrolledTextView. Et dans un autre endroit, vous voulez une bordure autour de la vue texte. Donc, vous sous-classe à nouveau et créez BorderedTextView. Eh bien, maintenant, dans un endroit, vous voulez une bordure et faites défiler les deux. Aucune des deux sous-classes précédentes n'a les deux capacités. Vous devez donc en créer un 3e. Lorsque vous créez un ScrolledBorderedTextView, vous dupliquez réellement l'effort. Vous n'avez pas besoin de cette classe si vous avez un moyen de composer la capacité des deux précédentes. Eh bien, les choses peuvent empirer et cela peut conduire à une explosion de classe inutile.
Fondamentalement, en utilisant le modèle de décorateur, vous pouvez ajouter un certain nombre de responsabilités supplémentaires à l'objet au moment de l'exécution que vous ne pouvez pas atteindre en sous-classant sans endommager potentiellement votre structure de code.
Mais une chose, les modèles de conception ne sont pas quelque chose que vous devez utiliser. Qu'un modèle soit nécessaire ou non dépend de votre problème particulier, vous souhaitez conserver le code pendant longtemps ou non, que vous souhaitiez l'étendre ou non et de nombreux autres facteurs comme ceux-ci. Et aucun modèle n'est utile dans tous les cas. Un motif (décorateur ou autre) adapté à une situation peut ne pas être un bon choix pour une autre situation.
Le livre GoF Design Patterns identifie deux avantages majeurs de l'utilisation de Decorators par rapport au sous-classement:
Plus de flexibilité que l'héritage statique. Le modèle Decorator fournit un moyen plus flexible d'ajouter des responsabilités aux objets que ce qui peut être fait avec l'héritage statique (multiple). Avec les décorateurs, les responsabilités peuvent être ajoutées et supprimées au moment de l'exécution simplement en les attachant et en les détachant. En revanche, l'héritage nécessite la création d'une nouvelle classe pour chaque responsabilité supplémentaire (par exemple, BorderedScrollableTextView, BorderedTextView). Cela donne lieu à de nombreuses classes et augmente la complexité d'un système. En outre, fournir différentes classes de décorateur pour une classe de composant spécifique vous permet de mélanger et de faire correspondre les responsabilités.
Les décorateurs facilitent également l'ajout d'une propriété deux fois. Par exemple, pour donner à TextView une double bordure, attachez simplement deux BorderDecorators. Hériter deux fois d'une classe Border est au mieux sujet aux erreurs.
Évite les classes riches en fonctionnalités en haut de la hiérarchie. Decorator propose une approche par répartition pour ajouter des responsabilités. Au lieu d'essayer de prendre en charge toutes les fonctionnalités prévisibles dans une classe complexe et personnalisable, vous pouvez définir une classe simple et ajouter des fonctionnalités de manière incrémentielle avec des objets Decorator. La fonctionnalité peut être composée de pièces simples. Par conséquent, une application n'a pas besoin de payer pour des fonctionnalités qu'elle n'utilise pas. Il est également facile de définir de nouveaux types de décorateurs indépendamment des classes d'objets qu'ils étendent, même pour des extensions imprévues. L'extension d'une classe complexe a tendance à exposer des détails sans rapport avec les responsabilités que vous ajoutez.
De mon point de vue, empêcher à lui seul l'explosion d'une sous-classe est assez convaincant.
Si vous avez un TextWindow
auquel vous souhaitez ajouter un défilement horizontal, un défilement vertical et des bordures de manière indépendante et facultative, en utilisant des sous-classes, vous devrez définir des sous-classes pour HorizontalScrollingTextWindow
, VerticalScrollingTextWindow
, HorizontalAndVerticalScrollingTextWindow
, BorderedTextWindow
, HorizontalScrollingBorderedTextWindow
, VerticalScrollingBorderedTextWindow
, HorizontalAndVerticaScrollingBorderedTextWindow
, et plus encore si vous vous souciez de l'ordre de défilement et en bordure.
Avec Decorators, il vous suffit de définir deux décorateurs à défilement et un décorateur de bordure.
Le sous-classement peut entraîner des problèmes avec le principe de substitution Liskov . Le décorateur évite cela.
Un autre avantage du décorateur est que vous écrivez (forcé d'écrire) sur une interface. Cela facilite les choses pour les tests. Il est vrai que votre hiérarchie d'objets peut également être écrite dans une interface et donc avoir certains des mêmes avantages, cependant, je peux tester une seule implémentation d'une classe décoratrice de manière isolée. Je ne peux pas faire la même chose avec une sous-classe car je ramènerai toujours toute la hiérarchie à la classe de base. Je ne peux pas tester le nouveau code de manière isolée.
En utilisant le modèle de décorateur et en suivant le principe de la responsabilité unique, je peux créer plusieurs décorateurs et les empiler comme je le souhaite. Je peux configurer cela au moment de l'exécution. En héritage, je dois soit créer toutes les branches possibles (a-> b-> c puis a-> c-> b, dupliquant ainsi le code et exploser le nombre de tests), soit je crée 1 hiérarchie puis j'en ajoute une si nécessaire, mais cela déclenche un nouveau cycle de test/libération.
C'est pourquoi vous voudriez utiliser le motif décorateur au lieu de sous-classer.
Voici les différences basées sur l'implémentation réelle.
La décoration est un autre moyen de sous-classer pour étendre les fonctionnalités des classes existantes. Voici un scénario où nous devrions utiliser le sous-classement ou le décorateur.
1) Le sous-classement principalement utilisé dans le cas de l'extension des fonctionnalités d'un groupe similaire de classes qui souhaite conserver les anciennes fonctionnalités ainsi que les nouvelles dans les sous-classes et toutes les instances des sous-classes partagent la même fonctionnalité. Si nous effectuons les changements de classes enfants et que cela reflétera toutes les instaces des classes enfants, comme une relation de hiérarchie, un groupe de classes similaire.
Parent-> Enfant-> GrandSon.
Voiture-> Maruti 800-> Maruti 100 (aura la caractéristique de Maruti 800 ainsi que Nouveau)
2) Le motif de décoration est utilisé pour décorer les classes existantes sans changer l'ancien comportement.Comme un cercle de classe a une bordure simple mais nous devons le décorer avec une bordure rouge, après un certain temps, certains utilisateurs veulent un cercle de couleur jaune et certains utilisateurs veulent un cercle avec une bordure verte et certains utilisateurs veulent un cercle de bordure rouge et jaune et certains utilisateurs veulent un cercle de bordure rouge et vert, etc., pour cela, c'est le modèle parfait car il ne réduira aucune classe de combinaison. Ci-dessous est l'exemple.
Icircle cir = nouveau RedDecorator (nouveau cercle ()) décorant le cercle de couleur rouge
Icircle cir = nouveau YellowDecorator (nouveau cercle ()) décorant le cercle de couleur jaune
Icircle cir = nouveau RedDecorator (nouveau YellowDecorator (nouveau cercle ())) décorant le
cercle avec rouge et jaune, ici nous n'avons pas besoin de créer un décorateur de classe RedAndYellow. de la même manière, nous pouvons décorer le cercle avec un autre ensemble de combinaisons sans créer de nouvel ensemble de classes de combinaisons.
De cette façon, il réduit le nombre de classes combinées.
Voici le lien utile pour le motif décorateur
https://www.tutorialspoint.com/design_pattern/decorator_pattern.htm
La flexibilité, c'est la raison pour laquelle l'OMI.