2009-07-13 5 views
6

Als Anfänger in der Programmierung stört es mich immer, wenn ich in eine Wand renne. Gegenwärtig sind eine der Wände co-abhängige Objekte.Java MVC - Fühle mich nicht wie ich es bekomme

Wie Sie in meinem Frageverlauf sehen können, arbeite ich gerade an einer Blackberry-Anwendung, in der ich etwas implementiert habe, das ich das MVC-Muster nenne, aber es ist nicht genau das, was ich denke.

Sie sehen, ein Anfänger Programmierer Sie auf Abstracts wie diese Grafik schauen und Sie bekommen die Idee dahinter. Aber es umzusetzen ist eine andere Sache.

alt text http://www.ibm.com/developerworks/wireless/library/wi-arch6/theoretical.gif

Bitte, hör nicht auf zu lesen :) Ich zeige Ihnen einige von mir Code, der etwas Brombeere spezielle Sachen enthält, aber Sie sollten sehen, was ich tue.

Haupteinstiegspunkt für meine Anwendung

public class ContactManager extends UiApplication 
{ 
    private static ContactManagerMainScreenModel MainScreenModel = new ContactManagerMainScreenModel(); 
    private static ContactManagerMainScreen MainScreenView = null; 

    public static void main(String[] args) 
    { 
     new ContactManager().enterEventDispatcher(); 
    } 
    public ContactManager() 
    { 
     MainScreenView = new ContactManagerMainScreen(MainScreenModel); 
     // Displays the Splashscreen then opens the Mainscreen 
     new SplashScreen(UiApplication.getUiApplication(), MainScreenView); 
    } 
} 

Die Hauptseite Modell

public class ContactManagerMainScreenModel 
{ 
    ContactManagerMainScreen v; 
    // Loading Local Storage 
    LocalContactStorage LocalContactStorage = new LocalContactStorage(); 

    // Define Data List 
    private Vector vContacts_Favorites; 

    public void register(ContactManagerMainScreen v) 
    { 
     this.v = v; 
    } 
    // Retrieve Favorite Contacts from Persistant Storage 
    public Vector getFavoriteContactsFromLocalStorage() 
    { 
     vContacts_Favorites = LocalContactStorage.getFavoriteContactsFromLocalStorage(); 
     return vContacts_Favorites; 
    } 
    // Put Retrieve Favorite Contacts from Persistant Storage 
    public void saveFavoriteContactsToLocalStorage() 
    { 
     LocalContactStorage.saveFavoriteContactsToLocalStorage(vContacts_Favorites); 
    } 
} 

Die MainScreenController

public class ContactManagerMainScreenController 
{ 
    private ContactManagerMainScreenModel _model = null; 
    private ContactManagerMainScreen _view = null; 

    public ContactManagerMainScreenController(ContactManagerMainScreen view, ContactManagerMainScreenModel model) 
    { 
     this._model = model; 
     this._view = view; 
    } 

    public void HideFavoriteList() 
    { 
     if(this._view._ContactList.getManager() != null) 
     { 
      this._view._ContactList.getManager().delete(this._view._ContactList); 
     } else 
     { 
      this._view._bottom_box.add(this._view._ContactList); 
     } 
    } 
} 

Immer noch da? Okay ...

Mein Problem hier ist, dass ich den Controller verwenden möchte, um UI-Elemente zu ändern, wie Anzeigen einer PopUp-Box, etwas oder andere Dinge ausblenden.

Aber alle diese UI-Elemente sind in der Ansicht (hier ContactManagerMainScreen) definiert, so dass Sie dem Controller einen Verweis auf die Ansicht geben müssen. Was zu meinen mit-abhängigen Objekten führt, Elend.

Ich kann den Controller nicht erstellen, bevor die Ansicht deklariert wird. Ohne die Anforderung, dem Controller zu erlauben, UIElements zu ändern, wäre dies kein Problem (wie in den Grafiken gezeigt).

Was jetzt ist ich tue, dass die Ansicht des Controllers Hat

controller = new ContactManagerMainScreenController(this , model); 

das macht Sinn schafft? Ich möchte das Muster verstehen, also nenne meinen Code Müll oder was auch immer du magst :) Ich will nur etwas lernen.

P.S. Ich bitte um Entschuldigung für mein schlechtes Englisch :)

Antwort

11

MVC ist eine interessante Abstraktion, hat aber einige Probleme.

In der Realität sind der Controller und die Ansicht oft gepaart - obwohl theoretisch in der Lage sein sollte, die einen ohne die andere zu ersetzen, in Wirklichkeit sind die Schnittstellenmechanismen zu verschiedenen Ansichten so unterschiedlich, dass die Controller & Ansicht kombiniert sind .

Die beste Beschreibung, die ich in Bezug auf Java gesehen habe, ist, dass die Ansicht Ihre Schwungkomponenten ist, so dass Ihr Teil des Ansichtscodes nichts anderes ist, als diese Komponenten auf dem Bildschirm zu platzieren.

Ihr Controller ist der Rest dieser Klasse, die Listener und der Rest Ihres Codes, der mit der Ansicht interagiert.

Mein Vorschlag zu viel nicht zu befürchten, wäre etwa die Ansicht und Steuerung zu isolieren, aber das heißt, ich bin total eine sehr starke Trennung zwischen dem Modell hinter halten und den Blick/Controller.

EDIT/Advanced: Ich habe ein Muster verwendet, wo Controller und Ansicht isoliert sind und es flexibler ist, aber es neigt dazu, viel mehr Arbeit zu sein. Ich denke, dass Struts das Binding-Modell verwendet - wenn Sie Abstraktionstechniken sehen möchten, können Sie dort nach Dingen suchen, die mit "bindenden" Swing-Controls zu tun haben.

+0

+1 stimme ich voll und ganz zu. – neuro

+0

+1 Dies entspricht auch meiner Erfahrung. – Zarkonnen

+0

(Obwohl, wenn irgendjemand * einen Standpunkt vertreten kann, wie man die Ansicht und den Controller vernünftig trennt, wäre ich sehr interessiert.) – Zarkonnen

1

Aus meiner Sicht ist dies etwas, was ich in lief, als ich versuchte zuerst meine Modelle zu trennen, Ansichten und Controller in meiner ersten Desktop-Anwendung. Das MVC-Muster passt bei Web-Anwendungen aufgrund der angeborenen Natur des Netzes sehr natürlich, aber leider ist es nicht möglich, ein reines MVC-Muster an eine Desktop-App anzupassen, bei der das Betriebssystem eine angeborene Rolle bei Benachrichtigungen spielt. Dies führt normalerweise dazu, dass das Muster so implementiert wird, wie Sie es in Ihrem Diagramm gezeigt haben.

jedoch das Muster, das Sie wirklich, wie diese umgesetzt werden gezeigt haben muss, denke ich (ich habe Sie bitte, dass im Auge behalten, so mit Java, nach einer kurzen Affäre .NET umgeschaltet):

public class ContactManagerMainScreenModel 
{ 
    ContactManagerMainScreen v; 
    // Loading Local Storage 
    LocalContactStorage LocalContactStorage = new LocalContactStorage(); 
    // Favorite list 
    boolean showFavoritesList = true; 

    public void register(ContactManagerMainScreen v) 
    { 
     this.v = v; 
    } 

    public void ShowOrHideFavoritesList() 
    { 
     if(showFavoritesList) 
     { 
      showFavoritesList = false; 
      v.RefreshView(this); 
     } 
     else 
     { 
      showFavoritesList = true; 
      v.RefreshView(this); 
     } 
    } 
} 

In der Zwischenzeit würde der Controller für das Empfangen von Benutzeraktionen verantwortlich sein. Wenn Sie also eine Schaltfläche haben, die "Favoriten ändern" anzeigt, würde der Controller _model.ShowOrHideFavoritesList() aufrufen. Das Modell aktualisiert sich selbst und fordert die Ansicht auf, sich mit dem neuen Status zu aktualisieren.

Die Ansicht würde nun frei von der Abhängigkeit vom Controller sein.

+0

Nochmals vielen Dank für Ihre Antwort. Ihre Implementierung würde zu einem Modell führen, das direkt die Benutzeroberfläche steuert. Würden Sie vorschlagen, den gesamten Controller fallen zu lassen? –

+0

Nein, bitte lesen Sie meine letzten zwei Absätze nach dem Code. Der Controller ist verantwortlich für die Behandlung aller Benutzerbenachrichtigungen. Hier ist ein anderes Beispiel. Nehmen wir an, der Benutzer klickt auf "Neuen Kontakt hinzufügen", der Controller würde dafür verantwortlich sein, _model.AddNewContact (String firstName, String lastName) aufzurufen. Das Modell würde diesen Kontakt dann seinem eigenen internen Status hinzufügen und dann RefreshView (this) in der Ansicht aufrufen. –

+0

Was ich meine ist, dass der Controller immer noch für die Erfassung aller Benutzerbenachrichtigungen verantwortlich ist und dann entscheidet, wie das Modell aktualisiert wird. Das Modell ruft dann immer RefreshView (this) auf der View auf, welches sich dann wieder selbst anzeigt ... –

3

Ich glaube nicht, dass dieses Diagramm sehr gut ist, und macht die Dinge wahrscheinlich viel verwirrender.

Der Controller sollte dafür verantwortlich sein, das Modell der Ansicht zu übergeben. Das Modell sollte nichts weiter als einfache Accessoren für Ihre Daten enthalten. Jegliche Notwendigkeit, mit dem Modell zu interagieren - oder irgendeinen seiner Werte zu ändern - sollte durch den Controller stattfinden.

Auf diese Weise muss die View nur wissen, wie das Modell für den Benutzer gerendert/präsentiert wird. Daher sollten alle Operationen auf dem Modell - Dinge wie saveFavoriteContactsToLocalStorage() - Methoden des Controllers sein, nicht die View-Klasse. Außerdem sollte der Controller keinen Verweis auf die zu erstellende Ansicht benötigen - ich denke, dass damit die beabsichtigte Reihenfolge des gesamten MVC-Musters umgekehrt wird.

+0

Ich glaube sein Diagramm ist korrekt. Das Problem ist, dass MVC keine gute Abstraktion ist und jedes Toolkit es so optimiert, dass es zu der Art passt, wie sie es entworfen haben. Manche machen gute Arbeit, manche nicht so gut - die eine Sache ist sicher, dass wenn Sie die Ansicht ändern, Sie am Ende den Controller wechseln werden (was gegen die Theorie ist). –

+0

Vielleicht. Ich bin nur sehr vertraut mit der Verwendung von MVC in Web-Kontexten, in welchem ​​Fall der Controller einfach die Ansicht und das Modell zurückgibt (wie in Spring MVC). Ich nehme an, es könnte auf dem Desktop anders sein. –

2

Ich stimme Bill K. Standard MVC ist nicht so wichtig im Umgang mit Rich-Client. Es ist ein großartiges Modell beim Schreiben von Web-Apps, da Ereignisse (Klicks in Ihrem Browser) sich stark von Ihrer Ansicht unterscheiden (HTML-Rendering).

Mit Standard-GUI ist ein besseres Modell etwas, das PAC (Präsentation/Abstraktion/Kontrolle) genannt wird. Hier ist die Präsentation (die Sicht + der Event-Handler), der Controller verwaltet den Austausch zwischen der Präsentation und der Abstraktion. Und die Abstraktion ist Ihr Geschäftsmodell.

diese Weise können Sie einen Controller haben, der die Verbindung zwischen dem GUI-Teil (Ansicht + Benutzerereignisse) und Ihre Abstraktion verwalten. Sie haben einen PAC-Agenten für jedes von Ihnen entwickelte GUI und eine saubere Trennung zwischen ihnen.

Ein weiterer Artikel über etwas besser als MVC im Zusammenhang mit PAC: HMVC. Ziemlich alt, aber es ist praktisch und es hilft, Dinge zu verstehen.

Verwandte Themen