Model View Control - Basiskonzepte
Um wirklich zu verstehen was das Model View Control (MVC) Paradigma bedeutet, muss man sich in die Rolle der GUI Frameworkentwickler versetzen. Diese entwickeln die GUI Komponenten mit denen dann später eine Anwendung entwickelt wird. Die GUI Komponenten dieses Frameworks haben dabei zwei wesentliche Eigenschaften:
MVC | Bestandteile |
---|---|
view | 1. GUI Komponenten (wie JTree) 2. Viewmodell-Implementierungen ihrer Viewmodell-Interfaces (wie TreeModel), die Viewmodell-Implementierungen sind über Model-Listener beim model angemeldet |
control | 1. Code in static void main(String[] args) 2. Code in Action-Listenern (angemeldet im view) 3. Code in Model-Listener (angemeldet im model) |
model | Fachdaten und Schnittstellen zum Anmelden/Abmelden von Model-Listener Implementierungen |
MVC vermeidet zyklische Abhängigkeiten
Wenn das MVC-Paradigma konsequent implementiert ist, werden zwischen model, view und control ausschließlich folgende direkten Abhängigkeiten realisiert:
Alle entgegengesetzt gerichteten (direkten) Abhängigkeiten sind komplett über das Observer-Pattern vermieden. Aus der Sicht der view ist control ein Listener für Action-Events, aus der Sicht des model sind view und control Listener für Model-Events:
Diese Grafik unterstreicht noch einmal die zentrale Motivation für MVC: das model ist komplett unabhängig von allen anderen Bestandteilen der GUI und könnte auch unabhängig von view und control genutzt werden (zum Beispiel für Unit-Tests).
Implementierung von view und control
Wie beschrieben werden im view hauptsächlich die Implementierungen der beteiligten Viewmodells bereit gestellt. Dabei ist vor allem auf diese Dinge zu achten:
Wie beschrieben erfolgt die Benachrichtigung bei Änderungen im model über Model-Listener, die von den Viewmodel-Interfaces der GUI Komponente und vom control implementiert werden. Geeignete Interfaces für diese Model-Listener sind somit zwingender Bestandteil des model-Designs und unvermeidlich, wenn das MVC-Designpattern umgesetzt werden soll. Kein GUI Framework kann das Design dieser Model-Listener vorwegnehmen, denn es ist spezifisch für die Struktur der Fachdaten der umzusetzenden Anwendung.
In einem ersten Entwurf kann dabei einfach ein "generisches" Model-Listener-Interface definiert werden:
interface IModelListener { // void contentChanged(); }Implementierungen können im model angemeldet (und natürlich auch abgemeldet) werden:
private final List<IModelListener> listenerList = new LinkedList<IModelListener>(); // Anmelden void addModelListener(IModelListener listener) { // synchronized(listenerList) { if (!listenerList.contains(listener) { listenerList.add(listener); } } } // Abmelden void removeModelListener(IModelListener listener) { // synchronized(listenerList) { listenerList.remove(listener); } } // Benachrichtigen: wird immer dann gerufen, // wenn sich im model etwas ändert private void notify() { synchronized(listenerList) { for (IModelListener listener : listenerList) { listener.contentChanged(); } } }Im Verlauf der Entwicklung kann dann dieses "generische" Model-Listener-Interface ausdifferenziert werden. Das bedeutet, dass spezialisierte Model-Listener-Interfaces für die verschiedenen Bereiche der Fachdaten definiert werden. Weiterhin könnten die Modelländerungen auch in contentChanged mit übergeben werden. Das alles sind spezifische Designentscheidungen und können nicht vorweg genommen werden.
Abhängigkeiten werden über import Statements in den beteiligten Klassen kontrolliert. Damit liegt auf der Hand, dass die verschiedenen Codeteile von model, view und control einer fachlichen Komponente auf unterschiedliche Pakete zu verteilen sind. Im einfachsten Fall sind das drei für model, view und control, komplexere fachliche Komponente können dann noch weiter unterteilen. MVC ist korrekt implementiert, wenn gilt:
Das MCV-Designpattern verhindert Abhängigkeiten vom model zum view und control und vom view zum control in einer Anwendung. Dadurch werden zyklische Abhängigkeiten zwischen model, view und control vermieden. Das model, verantwortlich für die Verwaltung von fachlichen Daten, kann dann unabhängig vom Rest der Anwendung entwickelt, genutzt und insbesondere leicht automatisiert getestet werden. Die Grundlage der Trennung ist die korrekte Implementierung der Viewmodel-Listener, die vom GUI Framework vorgegeben werden, sowie eine Benachrichtigung bei Änderungen im model über geeignete Model-Listener. Die Model-Listener sind damit zwingender Bestandteil eines MVC-konformen models.
Korrekt implementiertes MCV-Designpattern ist die Grundlage für eine funktionierende Implementierung bei nebenläufiger Abarbeitung in der GUI.