Im Delegatenmuster kann nur ein Objekt die Ereignisse eines anderen Objekts direkt abhören. Im Beobachtermuster kann eine beliebige Anzahl von Objekten die Ereignisse eines bestimmten Objekts abhören. Warum sollten Sie beim Entwerfen einer Klasse, die andere Objekte über Ereignisse benachrichtigen muss, jemals das Delegatenmuster über dem Beobachtermuster verwenden? Ich sehe das Beobachtermuster als flexibler. Möglicherweise haben Sie jetzt nur einen Beobachter, aber für ein zukünftiges Design sind möglicherweise mehrere Beobachter erforderlich.
9
Antworten:
Es gibt kein Delegatenmuster an sich. Ich gehe davon aus, dass Sie das Delegationsmuster meinen .
So wie ich es verstehe, sind sie völlig umgekehrt und werden für verschiedene Zwecke verwendet.
Im Allgemeinen hört bei einem Beobachtermuster eine beliebige Anzahl von Beobachterobjekten ein Ereignis auf einem zweiten Objekt ab und reagiert auf das Ereignis. Das zweite Objekt kennt seine Zuhörer nicht. Es ruft nur nach ihnen.
Ein Delegatenobjekt wird an das zweite Objekt übergeben, das Methoden direkt für den Delegaten aufruft. Und darin liegt der Vorteil, den Sie suchen. Anstatt eine einzelne Nachricht an mehrere Listener zu senden, hat sie die vollständige Kontrolle über ein einzelnes Objekt (zu einem bestimmten Zeitpunkt). Siehe auch Umkehrung der Kontrolle .
quelle
Sie sehen die Dinge falsch. Ein Beobachter sieht, dass ein bestimmtes Ereignis eintritt. Es wirkt sich nicht darauf aus oder besitzt es. Ein Delegat behandelt ein bestimmtes Ereignis und ist Eigentümer des Handlers, selbst wenn der Delegator die Schnittstelle zum Ereignis besitzt.
quelle
Das ist eine Frage mehrerer Kompromisse.
Kompromisse:
Delegiertenmuster:
Beobachtermuster:
quelle
Das Delegatenmuster ist, wie ich Sie verstehe, als Ereignishandlermechanismus in anderen Sprachen bekannt, zum Beispiel Delphi. Als solches ist es einfach eine Implementierung des Beobachtermusters mit einer großen Einschränkung: jeweils nur ein Zuhörer.
Der Nachteil von Event-Handlern oder Delegierten liegt auf der Hand: nur ein Beobachter.
Der Vorteil liegt nicht so auf der Hand: Leistung. Mit einem Beobachtermuster können Sie viele Beobachter hinzufügen. Wenn ein Ereignis eintritt, über das die Beobachter benachrichtigt werden müssen, müssen Sie die Beobachter auflisten und jeweils eine Benachrichtigung senden. Dies kann jede beobachtete Instanz schnell blockieren, insbesondere wenn die Anzahl der Ereignisse, für die eine Benachrichtigung erforderlich ist, ebenfalls erheblich ist.
quelle
int (*my_int_f)(int)
in C). Ich habe immer gedacht, dass sie das verständlicher gemacht hätten, indem sie es eher wie struct / enum funktionieren ließen. Ein Ereignis ist ein Hook für ein flexibles Array von Listenern, die eine einzelne Delegatensignatur verwenden. Sie könnten dies ohne ein Ereignis tun (weshalb ich davon ausgehe, dass das OP Delegationsmuster bedeutet, was sehr unterschiedlich ist), aber die Sprache macht es Ihnen leichter.Dies ist ein alter Beitrag, aber ich werde mich trotzdem einmischen, weil die anderen Antworten sich nicht mit dem befassen, was passiert, wenn eines der beiden Muster verwendet wird, sondern eher mit Theorie als mit Praxis.
Wie Delegation und Beobachter arbeiten
Mit Delegation wählt der Delegator genau aus, wer auf ein bestimmtes Ereignis reagieren wird, sobald die Quelle des potenziellen Ereignisses erstellt wird. Sie können sich diesen Zuhörer als einen einzigen Beobachter vorstellen . Im Fall des Beobachtermusters wählt der Beobachter aus, wen er beobachtet, wann immer er Lust dazu hat. Daher sind die Abhängigkeiten in Bezug auf Beobachter und Delegation umgekehrt. Stellen Sie sich mit dem Beobachtermuster eine Zeitung und Abonnenten als Beobachter vor. Die Beobachter haben die Kontrolle darüber, wann die Beziehung erstellt wird. Denken Sie bei der Delegation an einen Arbeitnehmer und einen Arbeitgeber. Der Arbeitgeber hat die Kontrolle darüber, wann die Beziehung hergestellt wird und wer genau für bestimmte Ereignisse verantwortlich ist. Mitarbeiter können nicht auswählen, an welchen Aufgaben sie arbeiten ... im Allgemeinen.
Einige Argumentationsdelegationen können einen Beobachter haben, aber ich denke, der wirkliche Unterschied zwischen den beiden besteht darin, wie die Ereignisbehandlung zugewiesen wird. Sie werden niemals einen Delegierten sehen, der sich für eine Veranstaltung registriert. Es wird nie erfahren, wie es das Ereignis überhaupt behandelt, bis es eintritt und der Delegator eine öffentliche Methode dafür aufruft.
Delegationsvorteil
Dieses Muster ist sehr starr und bei den meisten Regid-Designs einfacher und im Allgemeinen robuster. Es zwingt Sie, Ihren Ereignishandler zum Zeitpunkt der Initialisierung der Quelle des potenziellen Ereignisses im Voraus zu deklarieren. Wenn Sie jemanden brauchen, der den Verkehr leitet, weisen Sie einen Verkehrsleiter zu, bevor Sie die Straße öffnen. Im Falle des Beobachters würden Sie den Verkehrspolizisten jederzeit entscheiden lassen, wann der Verkehr geleitet werden soll, wann immer er oder sie Lust dazu hat.
Delegationsnachteil
Der Nachteil dieses Designs ist, dass es nicht flexibel ist. Wenn Sie einen Code zum Abonnieren einer Zeitung implementieren würden, müsste die Zeitung / der Delegator genau identifizieren, wer die Nachrichten in der Sekunde lesen kann, in der sie erstellt werden. Mit dem Beobachtermuster können sie jederzeit später registriert werden und die Zeitung muss nur wissen, dass sich eine neue Person angemeldet hat.
Wann sollte die Delegierung ausgewählt werden?
Wenn Sie mit Sicherheit einen bestimmten Beobachter benötigen und es keinen Grund gibt, zu ändern, wer beobachtet, ist das starre Design des Delegierungsmusters von Vorteil.
Beispielsweise benötigen Sie eine Klasse / ein Objekt, um ein Popup für einen bestimmten Fehler zu erstellen. Es gibt nicht viele Gründe, warum Sie zur Laufzeit wechseln müssten, wer einen bestimmten Fehler behandelt, sodass es sinnvoll wäre, den Fehler "Nicht genügend Speicher" an eine einzelne Entität zu delegieren. Es wäre nicht sehr sinnvoll, ein Array potenzieller Handler zu erstellen und diese Handler dann für den Fehler "Nicht genügend Speicher" registrieren zu lassen. Dies wäre ein Beispiel für die Verwendung des Beobachtermusters in dieser Situation. Zur Laufzeit möchten Sie möglicherweise ändern, welche Methoden aufgerufen werden oder welcher "Delegat" für variable Ereignisse aufgerufen wird, aber das Austauschen eines Ereignishandlers gegen ein bestimmtes Ereignis zur Laufzeit ist nicht normal.
Es ist nicht unmöglich, Delegierte auszutauschen, wie Sie es im Beobachtermuster tun würden, es ist einfach kompliziert. In der realen Welt möchten Sie vielleicht die Verkehrspolizisten tauschen, damit ein neuer Delegator den Verkehr abwickelt. Man könnte argumentieren, dass ein besseres Design den ursprünglichen Delegierten zu einer Polizeistation und nicht zu einem einzigen Polizisten machen würde, aber ich schweife ab ...
quelle