web-dev-qa-db-fra.com

Pourquoi devrais-je jamais utiliser une chaîne de responsabilité sur un décorateur?

Je suis en train de lire sur le modèle Chaîne de responsabilité et j’ai du mal à imaginer un scénario dans lequel je préférerais l’utiliser plutôt que celui de décorateur .

Qu'est-ce que tu penses? Le CdR a-t-il une utilisation de niche?

67
George Mauer

Le fait que vous puissiez rompre la chaîne à tout moment différencie le motif Chaîne de responsabilité du motif Décorateur . On peut penser que les décorateurs exécutent tous en même temps sans aucune interaction avec les autres décorateurs. Les liens d'une chaîne peuvent être considérés comme s'exécutant un par un, car ils dépendent chacun du lien précédent.

Utilisez le modèle de chaîne de responsabilité lorsque vous pouvez conceptualiser votre programme comme une chaîne composée de liens, chaque lien pouvant gérer une demande ou la transmettre dans la chaîne.

Lorsque je travaillais avec l'API Win32, j'avais parfois besoin d'utiliser la fonctionnalité de raccordement qu'elle fournit. Accrocher un message Windows suit à peu près le modèle de chaîne de responsabilité. Lorsque vous avez raccroché un message tel que WM_MOUSEMOVE, votre fonction de rappel est appelée. Pensez à la fonction de rappel en tant que dernier maillon de la chaîne. Chaque lien de la chaîne peut décider de jeter le message WM_MOUSEMOVE ou de le transmettre au prochain lien.

Si le motif Decorator avait été utilisé dans cet exemple, vous auriez été averti du message WM_MOUSEMOVE, mais vous seriez impuissant à empêcher d'autres hooks de le gérer également.

Un autre endroit où le modèle de chaîne de commandement est utilisé est celui des moteurs de jeu. Encore une fois, vous pouvez accrocher des fonctions de moteur, des événements et d’autres choses. Dans le cas d'un moteur de jeu, vous ne voulez pas simplement ajouter des fonctionnalités. Vous souhaitez ajouter des fonctionnalités et empêcher le moteur de jeu d'effectuer son action par défaut.

62
William Brendel

La différence entre ces modèles ne dépend pas du moment ou de la manière dont la chaîne peut être rompue (ce qui suppose une chaîne) ni du moment où le comportement supplémentaire est exécuté. Ils sont liés en ce qu'ils utilisent tous les deux la composition en faveur de l'héritage pour offrir une solution plus flexible.

La principale différence est qu'un décorateur ajoute nouveau comportement qui élargit en fait l'interface d'origine. Cela ressemble à la manière dont l'extension normale peut ajouter des méthodes, sauf que la "sous-classe" est uniquement couplée à une référence, ce qui signifie que toute "super-classe" peut être utilisée.

Le modèle COR peut modifier un comportement existant, ce qui revient à remplacer une méthode existante à l'aide de l'héritage. Vous pouvez choisir d'appeler super.xxx () pour continuer la "chaîne" ou gérer le message vous-même.

La différence est donc subtile, mais un exemple de décorateur devrait aider:

interface Animal
{
    Poo eat(Food food);
}

class WalkingAnimal implements Animal
{
    Animal wrapped;
    WalkingAnimal(Animal wrapped)
    {
        this.wrapped = wrapped;
    }

    Position walk(Human walker)
    {
    };

    Poo eat(Food food)
    {
      return wrapped.eat(food);
    }
}

class BarkingAnimal implements Animal
{
    Animal wrapped;
    BarkingAnimal(Animal wrapped)
    {
        this.wrapped = wrapped;
    }

    Noise bark()
    {
    };

    Poo eat(Food food)
    {
        bark();
        return wrapped.eat();
    }
}

Vous pouvez voir que nous pouvons composer un animal qui marche et qui aboie ... ou qui ajoute la capacité d'aboyer à n'importe quel animal. Pour utiliser ce comportement supplémentaire directement, nous aurions besoin de conserver une référence au décorateur BarkingAnimal.

Tous les BarkingAnimal aboient également une fois avant de manger, ce qui a modifié les fonctionnalités existantes et est donc similaire à un COR. Mais l’intention n’est pas la même que celle de COR, c’est-à-dire de trouver un animal sur beaucoup qui mangera la nourriture. L'intention ici est de modifier le comportement.

Vous pouvez imaginer un COR appliqué pour trouver un humain qui emmènera l'animal en promenade. Cela pourrait être implémenté comme une liste chaînée comme chained ci-dessus ou comme une liste explicite ... ou autre chose.

J'espère que c'est raisonnablement clair!

John

17
John Patterson

Chaîne

Évitez de coupler l'expéditeur d'une demande à son récepteur en donnant plus que un objet une chance de gérer le demande. Enchaîner les objets récepteurs et transmettez la demande le long de la chaîne jusqu'à ce qu'un objet le gère.

contre

Décorateur

Attribuez des responsabilités supplémentaires à un objet dynamiquement. Décorateurs fournir une alternative flexible à sous-classement pour extension fonctionnalité.

Je dirais que c'est dans l'ordre dans lequel les choses vont se passer. Si vous les enchaînez, ils seront appelés le long de la chaîne. Avec un décorateur, cette commande ne vous garantit pas que des responsabilités supplémentaires peuvent être attribuées.

13
Brian

Je dirais qu'une chaîne de responsabilité est une forme particulière de décorateur.

9
troelskn

Decorator est utilisé lorsque vous souhaitez ajouter des fonctionnalités à un objet.

Le COR est utilisé lorsque l'un des nombreux acteurs peut agir sur un objet.

Un particulier Decorator est appelé à effectuer une action en fonction du type; pendant que COR transmet l'objet le long d'une chaîne définie jusqu'à ce que l'un des acteurs décide que l'action est terminée.

Le COR peut être utilisé lorsqu'il existe plusieurs niveaux d'escalade hiérarchique vers différents gestionnaires - par exemple, un centre d'appels où la valeur client de l'entreprise pour l'entreprise détermine si l'appel passe à un niveau de support particulier.

6
Ragoczy

Eh bien, je peux penser à 2 situations: 

  • Vous n’avez pas d’objet principal, c’est-à-dire que vous ne savez pas quoi faire avec la demande après avoir passé tous les calques/filtres. (quelque chose comme un aspect comme les chaînes d'intercepteurs qui ne se soucient pas vraiment de l'endroit où la demande se termine).
  • Vous devez appliquer de manière sélective certains pré ou post-traitements à la demande. Pas sous forme d'amélioration générale comme le fait le décorateur. C'est-à-dire que les filtres peuvent ne pas traiter une requête spécifique, mais l'ajout d'un décorateur améliore toujours votre objet avec certaines fonctionnalités.

Je ne peux plus en penser pour le moment, aimerions en entendre davantage sur ce sujet.

4
MahdeTo

Décorateur

  1. Decorator pattern permet d'ajouter dynamiquement un comportement à un objet individuel.

  2. Il fournit une alternative flexible à sous-classification pour étendre les fonctionnalités. Même s'il utilise l'héritage, il hérite de l'interface du plus petit dénominateur commun (LCD).

Diagramme UML pour Decorator

 UML diagram for Decorator

Conséquences:

  1. Avec la décoration, il est également possible de supprimer dynamiquement les fonctionnalités ajoutées.
  2. Décoration ajoute des fonctionnalités aux objets lors de l'exécution, ce qui rendrait plus difficile le débogage des fonctionnalités du système.

Liens utiles:

Quand utiliser le motif de décorateur?

Decorator_pattern de wikipedia

décorateur de sourcemaking

Chaîne de responsabilité: _

Le modèle de chaîne de responsabilité est un modèle de conception constitué d'une source d'objets de commande et d'une série d'objets de traitement. Chaque objet de traitement contient une logique qui définit les types d'objets de commande qu'il peut gérer. le reste est passé à l'objet de traitement suivant dans la chaîne

Diagramme UML

 enter image description here

Ce modèle est plus efficace lorsque:

  1. Plus d'un objet peut gérer une commande
  2. Le gestionnaire n'est pas connu à l'avance
  3. Le gestionnaire doit être déterminé automatiquement
  4. Il est souhaitable que la demande soit adressée à un groupe d'objets sans spécifier explicitement son destinataire.
  5. Le groupe d'objets pouvant gérer la commande doit être spécifié de manière dynamique.

Liens utiles:

Chain-of-liability_pattern de wikipedia

modèle de chaîne de responsabilité de oodesign

chain_of_responsibility de la source

Exemple: : Dans une entreprise, un rôle désigné a des limites particulières pour le traitement de la demande d'achat. Si une personne ayant un rôle désigné n'a pas assez de pouvoir pour approuver une facture d'achat, elle transmettra la commande/demande à son successeur, qui dispose de plus de pouvoir. Cette chaîne continuera jusqu'à ce que la commande soit traitée.

2
Ravindra babu

Je conviens que du point de vue structurel, ces deux modèles sont très similaires. Ma pensée concerne le comportement final:

Dans l'interprétation classique de CoR, l'élément qui gère la demande rompt la chaîne. 

Si un élément du décorateur casse la chaîne, alors ce sera faux implémentation de décorateur, car la partie de base du comportement sera perdue. Et l'idée de décorateur est l'ajout transparent d'un nouveau comportement lorsque le comportement de base reste inchangé.

1
xenn_33
  1. mot clé 's'étend' - extension statique.
  2. Motif décoratif - extension dynamique.
  3. Modèle de chaîne de responsabilité - traitement d'un objet de commande avec un ensemble d'objets de traitement et ces objets ne se connaissent pas.
1
Oleksandr Markushyn

Je pense que les situations pour appliquer ces deux modèles sont différentes. Et d'ailleurs, pour les motifs de décorateur, le décorateur doit connaître le composant qu'il a enveloppé. Et pour le CdR, les différents intercepteurs ne pouvaient rien se connaître.

0
hewei1997

Après avoir lu les définitions du Gang of Four, je ne suis pas convaincu qu'il y ait une réelle différence. (inclus pour plus de commodité)

  • Décorateur: permet le wrapping dynamique des objets afin de modifier leurs responsabilités et comportements existants
  • Chaîne de responsabilité: Donne à plusieurs objets la possibilité de traiter une demande en reliant les objets récepteurs

Wikipedia les étoffe un peu, mais certaines sont un peu arbitraires.

  • Decorator est généralement implémenté sous forme de liste chaînée. Mais je pense que ce niveau est trop bas pour être considéré comme une "partie" du schéma.
  • Les liens de la chaîne de responsabilité ne traitent les données que si c'est leur responsabilité; Mais déterminer la responsabilité et le traitement des données font tous deux partie du comportement. Les décorateurs peuvent le faire aussi facilement.
  • Le décorateur exige que vous appeliez le délégué.
  • Un lien "pur" du CdR ne devrait appeler le délégué que s'il ne gère pas les données.

Les deux premiers attributs ne distinguent pas vraiment les modèles. Les deux autres le sont, mais la manière dont Decorator et le CdR sont généralement mis en œuvre ne fait pas respecter ces attributs. Le concepteur espère simplement que personne n'écrira un décorateur rompant la chaîne ou un lien CoRLink qui poursuit la chaîne après le traitement des données.

Pour réellement implémenter ces attributs, vous aurez besoin de quelque chose comme ce qui suit.

Décorateur forcé:

abstract class Decorated {

public Decorated delegate;

public final Object doIt(Object args) {
    Object returnVal = behavior(arg);
    if(delegate != null) returnVal = delegate.doit(returnVal);
    return returnVal;
}

protected abstract Object behavior(Object args); //base or subclass behavior
}

Chaîne de responsabilité forcée: 

abstract class Link {

public Link delegate;

public final Object processIt(Obect args) {
    Object returnVal = args;
    if(isMyResponsibility) returnVal = processingBehavior(returnVal);
    else returnVal = delegate.processIt(returnVal);
    return returnVal;
}

protected abstract Boolean isMyResponsibility(Object args);

protected abstract Object processingBehavior(Object args);
}

(Alternativement, vous pouvez simplement ajouter une ligne au javadoc, si tout ce que vous voulez, c'est vous en décharger de toute responsabilité au cas où quelqu'un d'autre bousillerait votre conception - mais pourquoi laisser cela au hasard?)

0
Kevin Sagan