Zasadniczo tak, należy stosować słabe odniesienia. Ale najpierw musimy wyjaśnić, co rozumiesz przez „słuchaczy wydarzeń”.
Callbacki
W niektórych stylach programowania, szczególnie w kontekście operacji asynchronicznych, część obliczeń jest często reprezentowana jako wywołanie zwrotne, które jest wykonywane w przypadku określonego zdarzenia. Na przykład Promise
[ 1 ] może mieć then
metodę, która rejestruje wywołanie zwrotne po zakończeniu poprzedniego kroku:
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
W tym przypadku zarejestrowane wywołania zwrotne then
muszą być utrzymywane przez silne odwołania, ponieważ obietnica (źródło zdarzenia) jest jedynym obiektem zawierającym odwołanie do wywołania zwrotnego. Nie stanowi to problemu, ponieważ sama obietnica ma ograniczony czas życia i będzie zbierana śmieci po zakończeniu łańcucha obietnic.
Wzór obserwatora
We wzorcu obserwatora podmiot ma listę zależnych obserwatorów. Gdy podmiot wchodzi w jakiś stan, obserwatorzy są powiadamiani zgodnie z jakimś interfejsem. Obserwatorów można dodawać i usuwać z tematu. Obserwatorzy ci nie istnieją w próżni semantycznej, ale z jakiegoś powodu czekają na wydarzenia.
Jeśli ten cel już nie istnieje, obserwatorzy powinni zostać usunięci z tematu. Nawet w językach, w których śmieci są gromadzone, usuwanie może wymagać ręcznego wykonania. Jeśli nie usuniemy obserwatora, zostanie on utrzymany przy życiu poprzez odniesienie od podmiotu do obserwatora, a wraz z nim wszystkie obiekty, do których odwołuje się obserwator. To marnuje pamięć i obniża wydajność, ponieważ (teraz bezużyteczny) obserwator będzie nadal powiadamiany.
Słabe referencje naprawiają ten wyciek pamięci, ponieważ pozwalają obserwatorowi na zbieranie śmieci. Gdy podmiot podchodzi, aby powiadomić wszystkich obserwatorów, i stwierdza, że jedno ze słabych odniesień do obserwatora jest puste, odniesienie to można bezpiecznie usunąć. Alternatywnie słabe referencje można zaimplementować w sposób, który pozwala podmiotowi zarejestrować wywołanie zwrotne czyszczenia, które usunie obserwatora po zebraniu.
Ale zauważ, że słabe referencje są jedynie pomocnikiem, który ogranicza szkody, zapominając o usunięciu obserwatora. Prawidłowym rozwiązaniem byłoby upewnienie się, że obserwator zostanie usunięty, gdy nie będzie już potrzebny. Opcje obejmują:
Robi to ręcznie, ale jest to podatne na błędy.
Używanie czegoś podobnego do try-with-resource w Javie lub using
w C #.
Deterministyczne zniszczenie, na przykład poprzez idiom RAII. Zauważ, że w języku z deterministycznym wyrzucaniem elementów bezużytecznych może to nadal wymagać słabych referencji od podmiotu do obserwatora, aby wyzwolić destruktor.