it-swarm.com.de

Warum sollte ich jemals eine Verantwortungskette gegenüber einem Dekorateur einsetzen?

Ich lese gerade über das Chain of Responsibility Muster nach und kann mir ein Szenario schwer vorstellen, in dem ich es vorziehen würde, das von Decorator zu verwenden.

Was denkst du? Hat der AdR eine Nische?

67
George Mauer

Die Tatsache, dass Sie die Kette jederzeit brechen können, unterscheidet das Verantwortungskettenmuster vom Decorator-Muster . Man kann sich vorstellen, dass Dekorateure auf einmal ausgeführt werden können, ohne mit den anderen Dekorateuren interagieren zu müssen. Man kann sich vorstellen, dass Links in einer Kette jeweils einzeln ausgeführt werden, da sie jeweils vom vorherigen Link abhängig sind.

Verwenden Sie das Chain of Responsibility-Muster, wenn Sie Ihr Programm als Kette aus Links konzipieren können, wobei jedes Link entweder eine Anfrage bearbeiten oder an die Kette übergeben kann.

Wenn ich früher mit der Win32-API arbeitete, musste ich manchmal die Hooking-Funktionalität nutzen, die es bietet. Das Ankoppeln einer Windows-Nachricht folgt grob dem Muster der Verantwortungskette. Wenn Sie eine Nachricht wie WM_MOUSEMOVE angehängt haben, wird Ihre Rückruffunktion aufgerufen. Stellen Sie sich die Rückruffunktion als das letzte Glied in der Kette vor. Jedes Glied in der Kette kann entscheiden, ob die WM_MOUSEMOVE-Nachricht weggeworfen oder an das nächste Glied übergeben werden soll.

Wenn das Decorator-Muster in diesem Beispiel verwendet worden wäre, wären Sie über die WM_MOUSEMOVE-Nachricht informiert worden. Sie können jedoch nicht verhindern, dass auch andere Hooks damit umgehen.

Ein anderer Ort, an dem das Befehlskette-Muster verwendet wird, ist in Spiel-Engines. Wieder können Sie Engine-Funktionen, Ereignisse und andere Dinge verknüpfen. Im Falle einer Spiel-Engine möchten Sie nicht einfach nur Funktionalität hinzufügen. Sie möchten Funktionen hinzufügen und verhindern, dass die Game-Engine ihre Standardaktion ausführt.

62
William Brendel

Der Unterschied zwischen diesen Mustern hängt nicht davon ab, wann oder wie die Kette unterbrochen werden kann (was eine Kette voraussetzt) ​​oder wann das zusätzliche Verhalten ausgeführt wird. Sie sind insofern verwandt, als beide die Zusammensetzung zugunsten der Vererbung verwenden, um eine flexiblere Lösung bereitzustellen.

Der entscheidende Unterschied ist, dass ein Dekorateur hinzufügt neu Verhalten, das die ursprüngliche Schnittstelle tatsächlich erweitert. Es ist ähnlich wie normale Erweiterungen Methoden hinzufügen können, mit der Ausnahme, dass die "Unterklasse" nur durch eine Referenz gekoppelt ist, was bedeutet, dass jede "Oberklasse" verwendet werden kann.

Das COR-Muster kann ein vorhandenes Verhalten ändern, das dem Überschreiben einer vorhandenen Methode mit Vererbung ähnelt. Sie können super.xxx () aufrufen, um die "Kette" fortzusetzen oder die Nachricht selbst zu bearbeiten.

Der Unterschied ist also geringfügig, aber ein Beispiel für einen Dekorateur sollte helfen:

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();
    }
}

Sie können sehen, dass wir ein gehendes, bellendes Tier zusammenstellen können ... oder tatsächlich die Fähigkeit hinzufügen, jedem Tier zu bellen. Um dieses zusätzliche Verhalten direkt verwenden zu können, müssen wir einen Verweis auf den BarkingAnimal-Dekorator beibehalten.

Alle BarkingAnimals bellen auch einmal vor dem Essen, was die vorhandene Funktionalität geändert hat und somit einem COR ähnelt. Die Absicht ist jedoch nicht die gleiche wie bei COR, d. H., Ein Tier von vielen zu finden, das die Nahrung aufnehmen wird. Die Absicht hier ist, das Verhalten zu ändern.

Sie können sich vorstellen, dass ein COR angewendet wird, um einen Menschen zu finden, der das Tier spazieren führt. Dies kann als verknüpfte Liste wie chained oben oder als explizite Liste ... oder was auch immer implementiert werden.

Hoffe das ist einigermaßen klar!

John

17
John Patterson

Kette

Vermeiden Sie, den Absender einer Anfrage zu koppeln zu seinem Empfänger, indem er mehr als ein Objekt eine Chance, die anfordern. Verketten Sie die Empfangsobjekte und übergeben Sie die Anforderung entlang der Kette bis ein Objekt damit fertig wird.

vs

Dekorateur

Fügen Sie weitere Verantwortlichkeiten zu .__ hinzu. ein Objekt dynamisch. Dekorateure bieten eine flexible Alternative zu Unterklasse für die Erweiterung Funktionalität.

Ich würde sagen, es ist die Reihenfolge, in der Dinge passieren werden. Wenn Sie sie verketten, wird das entlang der Kette aufgerufen. Bei einem Dekorateur kann Ihnen diese Bestellung nicht garantiert werden, es können nur zusätzliche Verantwortlichkeiten hinzugefügt werden.

13
Brian

Ich würde sagen, dass eine Kette der Verantwortung eine bestimmte Form von Dekorateur ist.

9
troelskn

Decorator wird verwendet, wenn Sie einem Objekt Funktionalität hinzufügen möchten.

COR wird verwendet, wenn einer von vielen Akteuren auf ein Objekt eingreift.

Ein insbesondere Decorator wird aufgerufen, eine Aktion basierend auf dem Typ auszuführen; während COR das Objekt entlang einer definierten Kette weitergibt, bis einer der Akteure entscheidet, dass die Aktion abgeschlossen ist.

COR kann verwendet werden, wenn es mehrere Eskalationsstufen für verschiedene Handler gibt - beispielsweise ein Callcenter, in dem der Wert des Kunden für das Unternehmen festlegt, ob der Anruf eine bestimmte Supportebene erreicht.

6
Ragoczy

Ich kann mir zwei Situationen vorstellen: 

  • Sie haben kein Kernobjekt, d. H. Sie wissen nicht, was mit der Anforderung zu tun ist, nachdem alle Ebenen/Filter durchlaufen wurden. (so etwas wie ein Aspekt wie Interceptor-Ketten, denen es egal ist, wo die Anfrage endet).
  • Sie müssen eine bestimmte Vor- oder Nachbearbeitung auf die Anforderung anwenden. Nicht in einer allgemeinen Verbesserung wie der Dekorateur. Filter können eine bestimmte Anforderung abwickeln oder auch nicht, aber das Hinzufügen eines Dekorators verbessert Ihr Objekt immer um einige Funktionen.

Kann mir im Moment nichts mehr vorstellen, würde gerne mehr über dieses Thema erfahren.

4
MahdeTo

Dekorateur

  1. Mit dem Muster Decorator kann das Verhalten einem einzelnen Objekt dynamisch hinzugefügt werden.

  2. Es bietet eine flexible Alternative zu sub classing zur Erweiterung der Funktionalität. Obwohl es Vererbung verwendet, erbt es von der Schnittstelle des untersten gemeinsamen Nenners (LCD).

UML-Diagramm für Decorator

UML diagram for Decorator

Folgen:

  1. Bei der Dekoration ist es auch möglich, die hinzugefügten Funktionalitäten dynamisch zu entfernen.
  2. Decoration erweitert Objekte zur Laufzeit um Funktionen, die die Funktionalität des Debugging-Systems erschweren würden.

Nützliche Links:

Wann wird das Dekoratormuster verwendet?

Decorator_pattern aus Wikipedia

Dekorateur von Sourcing

Verantwortungskette:

Das Verantwortungskettenmuster ist ein Entwurfsmuster, das aus einer Quelle von Befehlsobjekten und einer Reihe von Verarbeitungsobjekten besteht. Jedes Verarbeitungsobjekt enthält eine Logik, die die Typen von Befehlsobjekten definiert, die es verarbeiten kann. Der Rest wird an das nächste Verarbeitungsobjekt in der Kette übergeben

UML-Diagramm

enter image description here

Dieses Muster ist effektiver, wenn:

  1. Ein Objekt kann von mehr als einem Objekt verarbeitet werden
  2. Der Handler ist im Voraus nicht bekannt
  3. Der Handler sollte automatisch ermittelt werden
  4. Es wird gewünscht, dass die Anforderung an eine Gruppe von Objekten gerichtet ist, ohne dass der Empfänger explizit angegeben wird
  5. Die Gruppe von Objekten, die den Befehl verarbeiten kann, muss auf dynamische Weise angegeben werden

Nützliche Links:

Verantwortungskette_Pattern aus Wikipedia

Verantwortungskette von oodesign

Chain_of_responsibility aus der Beschaffung von Quellen

Beispiel aus der realen Welt: In einem Unternehmen unterliegen einer bestimmten Rolle bestimmte Beschränkungen für die Bearbeitung von Kaufanfragen. Wenn eine Person mit einer bestimmten Rolle nicht über die erforderlichen Befugnisse zur Genehmigung der Kaufrechnung verfügt, leitet sie den Befehl/die Anfrage an ihren Nachfolger weiter, der über mehr Befugnisse verfügt. Diese Kette wird fortgesetzt, bis der Befehl abgearbeitet ist.

2
Ravindra babu

Ich stimme zu, dass diese beiden Muster vom strukturellen Standpunkt aus sehr ähnlich sind. Ich denke über das endgültige Verhalten nach:

In der klassischen Interpretation des CoR-Elements, das die Anfrage bearbeitet, bricht die Kette. 

Wenn ein Element im Dekorateur die Kette durchbricht, ist dies die Implementierung von false des Dekorators, da der grundlegende Teil des Verhaltens verloren geht. Und die Idee des Dekorateurs ist die transparente Hinzufügung eines neuen Verhaltens, wenn das Basisverhalten unangetastet bleibt.

1
xenn_33
  1. schlüsselwort 'extend' - statische Erweiterung.
  2. Dekorateur-Muster - dynamische Erweiterung.
  3. Chain-of-Responsibility-Muster - nur die Bearbeitung eines Befehlsobjekts mit Eine Reihe von Verarbeitungsobjekten und diese Objekte kennen sich nicht.
1

Ich denke, die Situationen, in denen diese beiden Muster angewendet werden, sind unterschiedlich. Übrigens sollte der Dekorateur beim Dekorateur-Muster die Komponente kennen, die er einwickelt. Und für den AdR konnten die verschiedenen Abfangjäger nichts voneinander wissen.

0
hewei1997

Nachdem ich die Definitionen der Viererbande gelesen habe, bin ich nicht überzeugt, dass es einen echten Unterschied gibt. (für die Bequemlichkeit enthalten)

  • Dekorator: Ermöglicht das dynamische Umschließen von Objekten, um ihre vorhandenen Verantwortlichkeiten und Verhaltensweisen zu ändern
  • Verantwortungskette: Gibt mehr als einem Objekt die Möglichkeit, eine Anfrage zu bearbeiten, indem empfangende Objekte miteinander verknüpft werden

Wikipedia bringt sie etwas heraus, aber einige davon sind irgendwie willkürlich.

  • Decorator wird normalerweise als verknüpfte Liste implementiert. Aber ich denke, das ist zu niedrig, um als "Teil" des Musters betrachtet zu werden.
  • Chain-of-Responsibility-Links behandeln nur dann Daten, wenn dies in ihrer Verantwortung liegt. Die Festlegung von Verantwortung und Datenhandhabung sind jedoch beide Teil des Verhaltens. Dekorateure können dies genauso einfach tun.
  • Der Dekorateur muss den Delegierten anrufen.
  • Eine "reine" CoR-Verbindung sollte den Delegaten nur anrufen, wenn er die Daten nicht verarbeitet.

Die ersten beiden Attribute unterscheiden die Muster nicht wirklich. Die zweiten beiden tun dies, aber die Art und Weise, wie Decorator und der AdR normalerweise implementiert werden, setzt diese Attribute nicht durch. Der Designer hofft nur, dass niemand einen Decorator schreibt, der die Kette bricht, oder einen CoRLink, der die Kette nach der Verarbeitung der Daten fortsetzt.

Um diese Attribute tatsächlich zu implementieren, benötigen Sie Folgendes.

Erzwungener Dekorateur:

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
}

Erzwungene Verantwortungskette: 

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);
}

(Alternativ können Sie einfach eine Zeile zum Javadoc hinzufügen, wenn Sie nur die Verantwortung für den Fall ablehnen möchten, dass jemand anderes Ihr Design durcheinander bringt - aber warum dies dem Zufall überlassen?)

0
Kevin Sagan