Em geral, sim, referências fracas devem ser usadas. Mas primeiro precisamos esclarecer o que você quer dizer com "ouvintes de eventos".
Retornos de chamada
Em alguns estilos de programação, especialmente no contexto de operações assíncronas, é comum representar uma parte de um cálculo como um retorno de chamada que é executado em um determinado evento. Por exemplo, um Promise
[ 1 ] pode ter um then
método que registra um retorno de chamada após a conclusão da etapa anterior:
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
Aqui, os retornos de chamada registrados por then
devem ser mantidos por fortes referências, pois a promessa (a fonte do evento) é o único objeto que mantém uma referência ao retorno de chamada. Isso não é um problema, pois a promessa em si tem uma vida útil limitada e será coletada como lixo após a conclusão da cadeia de promessas.
Padrão do observador
No padrão do observador, um sujeito tem uma lista de observadores dependentes. Quando o sujeito entra em algum estado, os observadores são notificados de acordo com alguma interface. Os observadores podem ser adicionados e removidos do assunto. Esses observadores não existem no vácuo semântico, mas estão aguardando eventos para algum propósito.
Se esse objetivo não existir mais, os observadores devem ser removidos do assunto. Mesmo em idiomas coletados pelo lixo, essa remoção pode ter que ser realizada manualmente. Se não conseguirmos remover um observador, ele será mantido vivo por meio da referência do sujeito ao observador, e com ele todos os objetos que o observador fizer referência. Isso desperdiça memória e prejudica o desempenho, pois o observador (agora inútil) ainda será notificado.
Referências fracas corrigem esse vazamento de memória, pois permitem que o observador seja coletado como lixo. Quando o assunto avisa todos os observadores e descobre que uma das referências fracas a um observador está vazia, essa referência pode ser removida com segurança. Como alternativa, as referências fracas podem ser implementadas de uma maneira que permita ao sujeito registrar um retorno de chamada de limpeza que removerá o observador na coleta.
Mas observe que referências fracas são apenas um curativo que limitam o dano ao esquecer de remover um observador. A solução correta seria garantir que um observador seja removido quando não for mais necessário. As opções incluem:
Fazê-lo manualmente, mas isso é propenso a erros.
Usando algo semelhante à tentativa de recurso em Java ou using
em C #.
Destruição determinística, como através do idioma RAII. Observe que em um idioma com coleta de lixo determinística, isso ainda pode exigir referências fracas do sujeito para o observador, a fim de acionar o destruidor.