15.21 Das Konzept des Model-View-Controllers
Wir wollen uns noch einmal an die Idee des Observer-Patterns erinnern. Ein Beobachter beobachtet den zu Beobachtenden. Konkreter: Es meldete sich ein Beobachter an und wurde bei jeder Änderung der Daten informiert. Übertragen auf grafische Benutzungsoberflächen hieße das, es könnte unterschiedlichste Visualisierungen der Daten geben. Diese Trennung heißt auch Document-View-Struktur. Für grafische Oberflächen lässt sich dieses Modell zum Model-View-Controller (MVC) verfeinern. Die Idee stammte um 1978/79 ursprünglich von Professor Trygve Reenskaug am Xerox PARC und zog zuerst in Smalltalk ein.
Wie die drei Buchstaben von MVC andeuten, gibt es drei interagierende Objekte:
|
Modell: Es repräsentiert den internen Zustand eines Objekts und speichert alle interessanten Daten. Ein Modell bietet Methoden an, mit dem sich der aktuelle Zustand erfragen und ändern lässt. |
|
View: Die Daten des Modells werden im View dargestellt. Er nutzt die Methoden des Modells, um die Informationen auszulesen. |
|
Controller: Nach einer Interaktion mit der grafischen Oberfläche werden die Daten im Modell aktualisiert und anschließend vom Viewer wieder neu angezeigt. |
Diese Dreiteilung trennt alle Daten von der visuellen Repräsentation. Der große Vorteil dabei ist, dass sich alle drei Teile unterschiedlich entwickeln und einsetzen lassen. Die grafischen Komponenten können weiterentwickelt werden, und das Modell ändert sich nicht. In Java ist dies besonders aufgrund des wechselnden Aussehens interessant, denn dort gelangt zur Laufzeit ein neuer View zu seinem existierenden Modell.
Modifizierte MVC-Architektur für Swing
Das MVC-Konzept trennt ganz klar die Bereiche ab, führt aber bei praktischer Realisierung zu zwei Problemen. Das erste betrifft die Entwickler der Komponenten. Meistens sind View und Controller eng verbunden, so dass es zusätzlichen Schnittstellenaufwand für die Implementierung gibt. Implementieren wir etwa eine Textkomponente, müsste sie sich um alle Eingaben kümmern und diese dann an die Darstellung weiterleiten. Das zweite sich daraus ergebende Problem ist der erhöhte Kommunikationsaufwand zwischen den Objekten. Wenn sich Ergebnisse in der Darstellung oder dem Modell ergeben, führt die Benachrichtigung immer über den Controller.
Es macht demnach Sinn, VC zu einer Komponente zu verschmelzen, um die komplexe Interaktion zwischen View und Controller zu vereinfachen. Genauso haben es die Entwickler der JFC daher gemacht. In Swing findet sich keine Reinform des MVC, sondern eine Verquickung von View und Controller. Durch diese Vereinfachung lassen sich die Benutzeroberflächen leichter programmieren, wobei wir nur wenig Flexibilität einbüßen. Das neue Modell wird anstatt MVC auch Model-View-Presenter (MVP-Pattern) genannt. Betrachten wir das MVP-Konzept am Beispiel einer Tabellenkalkulation. Die Daten in einem Arbeitsblatt entsprechen den Daten, die unterschiedlich visualisiert werden können: klassisch in einem Tabellenblatt und modisch in einem Diagramm. Ein Modell kann problemlos mehrere Sichten haben. Eine Änderung der Daten im Tabellenblatt führt nun zu einer Änderung in den internen Daten, und umgekehrt führen diese zu einer Änderung des Diagramms.
Die Klasse ComponentUI und Modelle
In Java sind der View und der Controller durch ein Objekt ComponentUI repräsentiert. Da wir das Aussehen und Verhalten von Java-Komponenten frei bestimmen können, gibt es demnach für alle konkreten Swing-Komponenten ein ComponentUI-Objekt, welches die Darstellung und Benutzeraktionen übernimmt. Ein JList-Objekt verweist dann auf eine paint()-Methode im ComponentUI-Objekt, das die Darstellung wirklich vornehmen kann. Die Daten der Liste befinden sich im Modell.
Wenn wir uns mit einigen Modellen beschäftigen, werden wir sehen, dass für manche Komponenten sehr unterschiedliche Modelle gefordert sind. Eine Schaltfläche visualisiert meistens eine Zeichenkette. Eine Tabelle repräsentiert aber nicht immer nur einfache Texte. Hier können die Daten durchaus eine komplexe Objektstruktur darstellen. Um diese visualisieren zu können, muss der Viewer diese Daten auch bekommen. Dafür wird ein spezielles Modell implementiert, das die Daten für die Ansicht zur Verfügung stellt. Mit eigenen Modellen werden wir uns bei den Tabellen beispielhaft beschäftigen.
Modell
|
Klasse, die dieses Modell nutzt
|
ListModel
|
JList
|
ComboBoxModel
|
JComboBox
|
ButtonModel
|
JButton, JToggleButton, JCheckBox, JRadioButton, JMenu, JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem
|
Document
|
JTextField, JPasswordField, JTextArea, JEditorPane, JTextPane
|
BoundedRangeModel
|
JProgressBar, JScrollBar, JSlider
|
SingleSelectionModel
|
JMenuBar, JPopupMenu, JTabbedPane
|
TableModel
|
JTable
|
TableColumnModel
|
JTable
|
TreeModel
|
JTree
|
TreeSelectionModel
|
JTree
|
|