10.17Das Model-View-Controller-Konzept
Erinnern wir uns an die Idee des Observer-Patterns: Ein Beobachter beobachtet den zu Beobachtenden. Konkreter: Es meldete sich ein Beobachter an und wurde bei jeder Änderung der Daten informiert. Übertragen auf grafische Benutzeroberflächen, würde dies bedeuten, dass unterschiedlichste Visualisierungen der Daten möglich wären. 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 wurde um 1978/79 ursprünglich von Professor Trygve Reenskaug am Xerox PARC entwickelt und fand zuerst in Smalltalk Eingang.
Wie die drei Buchstaben von MVC andeuten, gibt es drei interagierende Objekte:
Model: Das Model repräsentiert den internen Zustand eines Objekts und speichert alle interessanten Geschäftsdaten. Ein Model bietet Methoden an, mit denen sich der aktuelle Zustand erfragen und ändern lässt.
View: Die View stellt die Daten des Models in einer Ansicht dar. Die Ansicht nutzt die Methoden des Models, um die Informationen auszulesen.
Controller: Nach einer Interaktion mit der grafischen Oberfläche werden die Daten im Model aktualisiert und anschließend vom Viewer neu angezeigt.
Diese Dreiteilung trennt alle Daten von der visuellen Repräsentation. Der große Vorteil besteht darin, dass sich alle drei Teile unterschiedlich entwickeln und einsetzen lassen. Die grafischen Komponenten können weiterentwickelt werden, und das Model ändert sich nicht. In Java ist dies besonders aufgrund des wechselnden Aussehens interessant, da dort zur Laufzeit eine neue View zu ihrem existierenden Model gelangt.
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 Problem betrifft die Entwickler der Komponenten. Meistens sind View und Controller eng verbunden, sodass ein zusätzlicher Schnittstellenaufwand für die Implementierung entsteht. 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 Model ergeben, führt die Benachrichtigung immer über den Controller.
Demnach ist es sinnvoll, VC (View und Controller) zu einer Komponente zu verschmelzen, um die komplexe Interaktion zwischen View und Controller zu vereinfachen. Genauso sind die Entwickler der JFC vorgegangen. In Swing findet sich keine Reinform des MVC-Models, 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 Model wird statt 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 modern in einem Diagramm. Ein Model kann problemlos mehrere Ansichten aufweisen. 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 die 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, das 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 Model.
Model-Klassen
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 erst bekommen. Dafür wird ein spezielles Model implementiert, das die Daten für die Ansicht zur Verfügung stellt. Mit eigenen Modellen werden wir uns bei den Tabellen in Abschnitt 10.19, »Tabellen (JTable)«, beispielhaft beschäftigen.
Model | Klasse, die dieses Model 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 |
Tabelle 10.10Einige Models und ihre Klassen