En general, sí, deben usarse referencias débiles. Pero primero tenemos que tener claro lo que quiere decir con "oyentes de eventos".
Devoluciones de llamada
En algunos estilos de programación, especialmente en el contexto de operaciones asincrónicas, es común representar una parte de un cálculo como una devolución de llamada que se ejecuta en un evento determinado. Por ejemplo, un Promise
[ 1 ] puede tener un then
método que registre una devolución de llamada al completar el paso 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
Aquí, las devoluciones de llamada registradas por then
deben ser retenidas por referencias fuertes, ya que la promesa (el origen del evento) es el único objeto que contiene una referencia a la devolución de llamada. Esto no es un problema, ya que la promesa en sí misma tiene una vida limitada, y se recolectará basura una vez que se complete la cadena de promesas.
Patrón de observador
En el patrón de observador, un sujeto tiene una lista de observadores dependientes. Cuando el sujeto entra en algún estado, los observadores son notificados de acuerdo con alguna interfaz. Los observadores pueden agregarse y eliminarse del sujeto. Estos observadores no existen en un vacío semántico, pero están esperando eventos para algún propósito.
Si este propósito ya no existe, los observadores deberían ser retirados del tema. Incluso en los idiomas recolectados de basura, esta eliminación podría tener que realizarse manualmente. Si no eliminamos un observador, se mantendrá vivo a través de la referencia del sujeto al observador, y con él todos los objetos a los que hace referencia el observador. Esto desperdicia memoria y degrada el rendimiento ya que el observador (ahora inútil) aún será notificado.
Las referencias débiles corrigen esta pérdida de memoria, ya que permiten que el observador sea recolectado como basura. Cuando el sujeto se da la vuelta para notificar a todos los observadores y encuentra que una de las referencias débiles a un observador está vacía, esa referencia se puede eliminar de forma segura. Alternativamente, las referencias débiles podrían implementarse de una manera que permita al sujeto registrar una devolución de llamada de limpieza que eliminará al observador al momento de la recolección.
Pero tenga en cuenta que las referencias débiles son solo una curita que limitan el daño al olvidar quitar un observador. La solución correcta sería asegurarse de que se elimine un observador cuando ya no sea necesario. Las opciones incluyen:
Hacerlo manualmente, pero es propenso a errores.
Usar algo parecido a probar con recursos en Java o using
en C #.
Destrucción determinista, como a través del idioma RAII. Tenga en cuenta que en un lenguaje con recolección de basura determinista, esto aún podría requerir referencias débiles del sujeto al observador para activar el destructor.