2010-07-22 8 views
5

Mi piacerebbe implementare il pattern MVC in una situazione difficile. La difficoltà è che i miei modelli (le entità che generano gli eventi) sono longevi, mentre i Views (i destinatari degli eventi) sono di breve durata. Il mio problema è che, attraverso la connessione tra i due, i modelli di lunga vita mantengono vivi i miei brevi live view, cioè non possono essere raccolti con garbage collection.Come implementare il pattern MVC senza mantenere vivi Views

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

Un modo per ovviare a questo è quello di memorizzare i collegamenti nel modello in un WeakHashMap < View, controller >. Questo essenzialmente fa in modo che la View sia spazzatura, e quando ciò accade, la WeakHashMap lancia anche il Controller corrispondente. Cioè, se il Controller non ha un riferimento (forte) alla Vista - cosa che di solito fa. In questo caso, le viste vengono mantenute in vita attraverso i riferimenti forti finché il modello non viene spostato.

C'è un altro modo per collegare i listener ai miei modelli che non mantengono vivi i miei punti di vista (e i miei controller)?

UPDATE: Per rispondere alla domanda di mdma: il controller mantiene un riferimento alla vista, poiché è necessario aggiornare la vista. Questo riferimento può essere debole, ma mi piacerebbe che i Controllori fossero classi interne anonime della classe View, nel qual caso l'istanza Controller ha un riferimento implicito forte all'istanza View.

+0

Perché il controller hanno un forte riferimento alla vista? – mdma

risposta

0

Here hai una grande implementazione del pattern MVC. C'è probabilmente una soluzione per il tuo problema.

+0

Forse mi manca qualcosa, ma questo sembra un * demo * su come usare Swing's MVC? Inoltre, l'implementazione di Swing del pattern MVC non è una soluzione per il mio problema, poiché mantiene forti riferimenti tra i modelli e gli ascoltatori. –

3

Ci sono alcuni modi per fare MVC.

  • Scrivere un modello quindi consentire alla vista di ascoltare le modifiche al modello. La vista dice al controller quando succede qualcosa.
  • Scrivere una vista, quindi lasciare che il modello ascolti le modifiche alla vista. La vista dice al controller quando succede qualcosa.
  • Scrivi una vista. Lascia che il tuo modello ascolti le modifiche alla vista. Lascia che il tuo controller ascolti la vista, che genererà eventi diversi se succede qualcosa.

L'ultimo fornisce l'accoppiamento più debole tra visualizzazioni, controller e modelli. È un bastardo testare l'unità del controller perché si finisce per dover fermare i gestori di eventi. Non puoi nemmeno prenderli in giro usando strutture di derisione, perché hai bisogno di aumentare gli eventi per tutto il tempo. Funziona, però.

mi piace MVCP:

  • Consentire il controller per avvolgere il modello in un presentatore. Il Controller è in ascolto per le Viste collegate e consegna loro un nuovo Presenter ogni volta. Il relatore delega le modifiche di campo al modello e delega anche i comandi al controller. Né il Controller né il Modello si appendono a un riferimento al Presenter. Quando la vista muore, il presentatore lo segue.

La cosa grandiosa di presentatori è che si può incapsulare solo la roba che le esigenze di visualizzazione. L'interfaccia per un presentatore è quasi interamente guidata dalla vista. Puoi anche fare cose come creare diversi presentatori per diverse viste e popolarle tutte attraverso un unico metodo di interfaccia come questo: Presenter.PopulateWith(model, controller).Questo ti dà un ottimo posto per fare tutta la logica di presentazione (date in stringhe, nomi di login senza lo ., ecc.) Senza inquinare il tuo adorabile Modello. E ottieni la tua debole referenza gratuitamente!

Questo è molto simile al pattern MVVM ora utilizzato in WPF idiomatico. Funziona bene in Java, anche con il Web. Spero che questi ti diano qualche idea, comunque.

0

Penso che tu sia sulla buona strada. Vedo due possibili soluzioni per ottenere viste correttamente bonificate:

  1. design la vista vita nel sistema, in modo che vista descruction è fatto in modo esplicito, e tutte le parti interessate possono quindi rilasciare i loro riferimenti alla vista.

  2. Rimuovere il riferimento forte nel controller. Il controller può utilizzare un WeakReference per mantenere la vista, che deve essere controllata con ciascun accesso, oppure passare il controller a Visualizza l'implementazione che delega alla vista reale, trattenendola tramite un riferimento debole. Se il riferimento è stato recuperato (è nullo), la chiamata al metodo è un no-op.

0

... ma mi piacerebbe avere i controller di essere anonime interne classi della classe View, nel qual caso l'istanza controller ha un forte riferimento implicito all'istanza View.

Questo semplicemente non funzionerà ... basato sui diagrammi nella domanda.

Un riferimento regolare nella Model al Controller e un altro nel Controller alla visualizzazione sarà sufficiente a significare che il View è fortemente raggiungibile. Di conseguenza, il riferimento debole nello Controller allo View non verrà interrotto ... fino a quando lo stesso diventa idoneo per la garbage collection.

Poiché una classe interna anonima non può mai essere statica, non si ha una scelta ragionevole (*) ma per rendere il controller una classe nidificata statica o una classe non nidificata.

L'altra alternativa sarebbe quella di rendere il collegamento dal modello al controller un riferimento debole.

(* In realtà c'è un trucco che potrebbe eventualmente funzionare ... anche se è quasi troppo orribile parlare. Si poteva capire ciò che il nome dell'attributo nascosto che tiene collegamento dell'oggetto Controller per il suo oggetto genitore, e magari utilizzare la riflessione per trovare la Field e quindi utilizzare tale per impostare l'attributo di null.)


EDIT

Questo è ciò che la J LS parla di classi anonime - JLS 15.9.1

Una classe anonima non è mai astratta (§8.1.1.1). Una classe anonima è sempre una classe interiore (§8.1.3); non è mai statico (§8.1.1, §8.5.2). Una classe anonima è sempre implicitamente definitiva (§8.1.1.2).

Sto avendo difficoltà a conciliare questo con il commento del PO ...

+0

In realtà, è possibile avere una classe interna anonima statica se la si definisce in un contesto statico (vale a dire in un metodo statico o come campo statico di una classe). Questa è la soluzione che stiamo usando ora per garantire che l'ascoltatore non faccia riferimento alla vista, ma risulta in un codice orribile ed è molto soggetta a errori. Ecco perché sto cercando una soluzione migliore. –

Problemi correlati