MVC – Funktion und einfaches Beispiel

MVC – wer damit noch nichts gemacht hat und es programmieren soll, wird auf den ersten Blick verwirrt sein – und auf den zweiten Blick auch. Wenn man dann denkt, dass man es begriffen hat, verwirrt das Interface und die Tätigkeiten des Frameworks nochmals. Ich hoffe, mit diesem Beitrag einige Unklarheiten beseitigen zu können und einfaches Beispiel liefern zu können.

Zum einen werden bei MVC eigens dafür erstellte Klassen verwendet, dann wieder Funktionen des Frameworks. Es gibt nicht die Klasse MVC selbst; es ist für Einsteiger auf dem Weg zum Fortgeschrittenen ein ziemlich abgehobenes Konstukt („abstrakt“ – um auch dieses Wort verwendet zu haben.) Aber alles der Reihe nach. Der Blog lehnt sich an dem beiliegenden Beispiel an. Dieses kann hier heruntergeladen werden: simplesample

M – Das Model. Das Model ist im vorliegen den Fall (und es dürfte viele Fälle abdecken) genau 1x vorhanden. Es wird von Model nur eine Instanz erstellt. Darin sind alle Funktionen enthalten um die Daten des Programms zu verwalten. Es ist die zentrale Stelle um Daten abzulegen, zwischenzuspeichern und zur Verfügung zu stellen (z.B. Formeln zur Berechnung von Ergebnissen oder die bekannten getter und setter).

V – der Viewer. Der oder die Viewer (MVC ist erst richtig stark und effizient, wenn es viele Viewer gibt, die Daten anzeigen) wird an das Model geknüpft und ist letztlich dafür zuständig, die Daten aus dem Model anzuzeigen, d.h. die typische setText-Methoden zum Editieren der Oberfläche primitiver Steuerelemente (wie z.B. ein Label) erfolgen in diesen Klassen und NICHT in der Model-Klasse. Typisch: die Funktion erfolgt dort wo sie benötigt wird.

C – der Commander. Diese Komponente besitzt die Möglichkeit des Zuhörens oder des Lauschens („Listener“): kommt ein Input-Signal, werden i.d.R. Daten im Model manipuliert und das Model kennt die Anzeigeelemente und kontaktiert diese für ein Update.

Ablauf: angenommen, ein Frame besitzt ein Textfield und einen Slider – die Typen sind vollkommen egal. Es könnte genau so gut ein Spinner, ein Label oder eine Combo sein – egal. Der Slider wird bedient und das Label oder Textfeld ändert den Inhalt – soweit.

Dabei ist das Controller-Element der Slider und das View wird als Textfield dargestellt. Im Hintergrund werkelt das Model und kümmert sich um die Annahme der Sliderdaten sowie um die Kontaktierung des Textfields.

thomas-zehrer-de_mvc1-01

Abbildung: MVC an einem einfachen Beispiel.

Etwas genauer zur Vorbereitung: Die Datenbasis für die Daten, die Slider an das Textfeld weiter gibt wird zunächst initialisiert (Model m) – das Model. Im Anschluß wird der Frame gezeichnet und das Slider-Steuerelement eingesetzt. Auf das Steuerelement (bzw. über eine Ableitung davon – näheres weiter unten) wird über eine Controller-Klasse, die das Change-Ereignis abfängt, ein Listener gesetzt (SliderController sc = new SliderController (m)) und slider. addChangeListener(sc)). Damit sind wir beim Controller. Damit wird ein ausgelöstes Ereignis abgefangen und die Änderung dem Model übergeben, wenn der Slider verschoben wird (m.setNumber(s.getValue())). Somit ist der Slider fertig.

Zu den Views: Als Ausgabe wird ein Objekt erzeugt, das von einem Textfield abgeleitet wurde. Wieso eine Ableitung und nicht direkt das Textfield? Weil es durch Hinzufügen eigener Kontaktfunktionen wie gesagt die Möglichkeit der Verbandelung von Model mit View gibt und am View die Funktion  zur Änderung der Textfield-Inhalte über das Model kontaktiert wird (numberValueChanged(Model m, int s)). Woher weiß jetzt das Model, das es ein Textfield-Objekt gibt und es informiert werden muss? Es gibt am Model einen Sammler, bei dem ein zu informierendes Steuerelement registriert wird (private ArrayList<Interface> listeners mit m.addSteuerelementeListener (textfield)). Damit die Verwirrung komplett ist (Anm. des Erstellers ;-)) wird hier das Interface erwähnt: Das ArrayList zum Sammeln der Viewer-Steuerelemente speichert Objekte vom Typ Interface. Das Interface wird über die Viewer registriert. Zum einen werden die Funktionen des Interfaces an die registrierten Objekte erzwungenermaßen verteilt und zum Zweiten kann ein jedes Objekt, das die Methoden des Interfaces implementiert über das Interface angesprochen werden. Man kann sagen, dass Interface dient als eine zentrale Anlaufstelle und maskiert sich als das Objekt, das im Moment benötigt wird. Wird Interface bei einem Textview implementiert, kann es als solches behandelt werden; richtet sich die Anfrage an ein Label und wird bei der Erstellung des Labels das Interface implementiert, wird umgekehrt das Label über die Interface-Methoden angesprochen.

Kann man das auch Visualisieren? Solange man nicht durchblickt, kann man sich zur Hilfe ein Bild malen. Dann wirds klarer. Dafür eignen sich die sogenannten statischen Klassendiagramme um Abhängigkeiten darzustellen. Bitte informieren Sie sich über zu verwendete Komponenten in UML-Diagrammen. Ich liefere das Diagramm zeitnah nach.

SimpleSample kann in ein neue Eclipse-Projekt eingebunden werden. Setzen sie sich Debug-Punkte und fügen Sie bei Bedarf sysouts ein. Sie werden nach einiger Zeit sehen wie der Ablauf ist. Viel Spaß damit.