Im Allgemeinen sollten ja schwache Referenzen verwendet werden. Aber zuerst müssen wir uns darüber im Klaren sein, was Sie unter „Event-Listenern“ verstehen.
Rückrufe
In einigen Programmierstilen, insbesondere im Zusammenhang mit asynchronen Operationen, ist es üblich, einen Teil einer Berechnung als Rückruf darzustellen, der bei einem bestimmten Ereignis ausgeführt wird. Zum Beispiel kann eine Promise
[ 1 ] eine then
Methode haben, die einen Rückruf nach Abschluss des vorherigen Schritts registriert:
promise =
Promise.new(async_task) # - kick off a task
.then(value => operation_on(value)) # - queue other operations
.then(value => other_operation(value)) # that get executed on completion
... # do other stuff in the meanwhile
# later:
result = promise.value # block for the result
Hier müssen die von registrierten Rückrufe then
von starken Referenzen gehalten werden, da das Versprechen (die Ereignisquelle) das einzige Objekt ist, das eine Referenz auf den Rückruf enthält. Dies ist kein Problem, da das Versprechen selbst eine begrenzte Lebensdauer hat und nach Abschluss der Versprechenskette als Müll gesammelt wird.
Beobachtermuster
Im Beobachtermuster hat ein Subjekt eine Liste abhängiger Beobachter. Wenn das Subjekt in einen Zustand eintritt, werden die Beobachter gemäß einer bestimmten Schnittstelle benachrichtigt. Beobachter können dem Motiv hinzugefügt und daraus entfernt werden. Diese Beobachter existieren nicht in einem semantischen Vakuum, sondern warten auf Ereignisse zu einem bestimmten Zweck.
Wenn dieser Zweck nicht mehr besteht, sollten die Beobachter aus dem Subjekt entfernt werden. Selbst in durch Müll gesammelten Sprachen muss diese Entfernung möglicherweise manuell durchgeführt werden. Wenn wir einen Beobachter nicht entfernen, wird er über die Referenz des Subjekts zum Beobachter und damit alle Objekte, auf die der Beobachter verweist, am Leben erhalten. Dies verschwendet Speicher und beeinträchtigt die Leistung, da der (jetzt unbrauchbare) Beobachter weiterhin benachrichtigt wird.
Schwache Referenzen beheben dieses Speicherleck, da sie es dem Beobachter ermöglichen, Müll zu sammeln. Wenn das Subjekt herumgeht, um alle Beobachter zu benachrichtigen, und feststellt, dass einer der schwachen Verweise auf einen Beobachter leer ist, kann dieser Verweis sicher entfernt werden. Alternativ könnten die schwachen Referenzen so implementiert werden, dass der Betreff einen Bereinigungsrückruf registrieren kann, der den Beobachter beim Sammeln entfernt.
Beachten Sie jedoch, dass schwache Referenzen nur ein Pflaster sind, das den Schaden begrenzt, indem es vergisst, einen Beobachter zu entfernen. Die richtige Lösung wäre, sicherzustellen, dass ein Beobachter entfernt wird, wenn er nicht mehr benötigt wird. Zu den Optionen gehören:
Manuell machen, aber das ist fehleranfällig.
Verwenden Sie etwas Ähnliches wie das Ausprobieren mit Ressourcen in Java oder using
in C #.
Deterministische Zerstörung, etwa über das RAII-Idiom. Beachten Sie, dass in einer Sprache mit deterministischer Speicherbereinigung möglicherweise noch schwache Verweise des Subjekts auf den Beobachter erforderlich sind, um den Destruktor auszulösen.