2010-07-22 32 views
5

Me gustaría implementar el patrón MVC en una situación difícil. La dificultad es que mis Modelos (las entidades que generan los eventos) son de larga duración, mientras que las Vistas (los receptores de los eventos) son de corta duración. Mi problema es que a través de la conexión entre los dos, los Modelos de larga vida mantienen vivas mis visiones efímeras, es decir, no pueden recogerse basura.Cómo implementar el patrón MVC sin mantener Vistas activas

[MODEL] ------- <weak> -------> [VIEW] 
    | 
<strong> 
    | 
    v 
[CONTROLLER] 

Una forma de evitar esto es para almacenar las conexiones en el modelo en un WeakHashMap < Vista, Controlador >. Esto esencialmente permite que la Vista sea basura, y cuando eso sucede, WeakHashMap arrojará el Controlador correspondiente también. Es decir, si el controlador no contiene una referencia (fuerte) a la vista, lo que generalmente hace. En este caso, las Vistas se mantienen activas a través de las referencias fuertes hasta que el Modelo sale del alcance.

[MODEL] ------- <weak> -------> [VIEW] 
    |        ^
<strong>       | 
    |        | 
    v        | 
[CONTROLLER] ----------- <strong> ---/ 

¿Hay otra manera de unir a los oyentes a mis modelos que no va a mantener mis puntos de vista (y controladores) vivo?

ACTUALIZACIÓN: Para responder la pregunta de mdma: el controlador mantiene una referencia a la vista, porque necesita actualizar la vista. Esta referencia puede ser débil, pero me gustaría que los Controladores sean clases internas anónimas de la clase Vista, en cuyo caso la instancia del Controlador tiene una referencia fuerte implícita a la instancia de la Vista.

+0

¿Por qué el controlador tiene una fuerte referencia a la vista? – mdma

Respuesta

0

Here tiene una gran implementación del patrón MVC. Probablemente haya una solución para su problema.

+0

Tal vez me esté perdiendo algo, pero esto parece una * demo * de cómo usar Swing's MVC? Además, la implementación de Swing del patrón MVC no es una solución para mi problema, ya que mantiene fuertes referencias entre los modelos y los oyentes. –

3

Hay algunas maneras de hacer MVC.

  • Escriba un modelo y luego deje que su vista escuche los cambios en el modelo. La vista le dice al controlador cuando sucede cualquier cosa.
  • Escriba una vista y luego permita que su modelo escuche los cambios en la vista. La vista le dice al controlador cuando sucede cualquier cosa.
  • Escribir una opinión Deje que su modelo escuche los cambios en la vista. Deje que su controlador escuche la vista, lo que provocará diferentes eventos si sucede algo.

El último da el acoplamiento más débil entre vistas, controladores y modelos. Es un bastardo probar la unidad por un solo controlador porque terminas teniendo que anclar los manejadores de eventos. Ni siquiera puedes burlarte de ellos utilizando marcos burlones, porque necesitas plantear eventos todo el tiempo. Sin embargo, funciona.

me gusta MVCP:

  • Permitir su controlador para envolver el modelo en un presentador. El controlador escucha las vistas adjuntas y les entrega un nuevo presentador cada vez. El presentador delega los cambios de campo al modelo y también delega los comandos al controlador. Ni el controlador ni el modelo se aferran a una referencia al presentador. Cuando la vista muere, el presentador la acompaña.

La gran cosa acerca de los presentadores es que se puede encapsular simplemente la materia que las necesidades de visualización. La interfaz para un presentador está casi completamente impulsada por la vista. Incluso puede hacer cosas como crear diferentes presentadores para diferentes vistas y completarlas a través de un método de interfaz como este: Presenter.PopulateWith(model, controller).Esto le proporciona un excelente lugar para hacer toda la lógica de la presentación (fechas en cadenas, nombres de inicio de sesión sin el ., etc.) sin contaminar su encantador modelo. ¡Y obtienes tu referencia débil gratis!

Esto es muy similar al patrón MVVM ahora utilizado en WPF idiomático. Funciona bien en Java, también con Web. Espero que estos te den algunas ideas, de todos modos.

0

Creo que está muy en el camino correcto. Veo dos soluciones posibles para conseguir vistas adecuadamente recuperadas:

  1. la vista Diseño de por vida en el sistema, de modo que la vista descruction se realiza de forma explícita, y todas las partes interesadas a continuación, puede liberar sus referencias a la vista.

  2. Elimina la referencia fuerte en el controlador. El controlador puede usar una WeakReference para aferrarse a la vista, que debe verificarse con cada acceso, o en su lugar, pasarle al controlador una implementación de Vista que delegue en su vista real, manteniéndola a través de una referencia débil. Si la referencia ha sido recuperada (es nula), la llamada al método no es operativa.

0

... pero me gustaría tener los controladores ser internos clases anónimas de la clase View, en cuyo caso la instancia controlador tiene una fuerte referencia implícita a la instancia de vista.

Eso simplemente no funcionará ... basado en los diagramas de la pregunta.

una referencia habitual en el Model a la Controller y otro en el Controller a la vista será suficiente para significar que el View es muy accesible. Como resultado, la referencia débil en el Controller al View no se romperá ... hasta que el Model sea elegible para la recolección de basura.

Dado que una clase interna anónima nunca puede ser estática, no tiene una opción razonable (*) pero para hacer que el Controlador sea una clase anidada estática o una clase no anidada.

La otra alternativa sería hacer que el enlace del Modelo al Controlador sea una referencia débil.

(* En realidad no es un truco que posiblemente podría funcionar ... aunque es casi demasiado horrible para hablar. Se puede averiguar cuál es el nombre del atributo oculto que lleva a cabo el enlace del objeto Controlador de su objeto primario, y tal vez utilizar la reflexión para encontrar el Field y luego utilizar eso para establecer el atributo en null.)


EDITAR

Esto es lo que el J LS dice sobre clases anónimas - JLS 15.9.1

Una clase anónima nunca es abstracta (§8.1.1.1). Una clase anónima es siempre una clase interna (§8.1.3); nunca es estático (§8.1.1, §8.5.2). Una clase anónima siempre es implícitamente final (§8.1.1.2).

estoy teniendo dificultades para conciliar esto con el comentario de la OP ...

+0

En realidad, puede tener una clase interna anónima estática si la define en un contexto estático (es decir, en un método estático o como un campo estático de una clase). Esta es la solución que estamos usando ahora para garantizar que el oyente no haga referencia a la vista, pero resulta en un código horrible y es muy propenso a errores. Es por eso que estoy buscando una mejor solución. –

Cuestiones relacionadas