Vorstellung
Ich bin Geschäftsführer der PartMaster GmbH und als Java-Architekt mit den Schwerpunkten Rich Client Platform, Data Binding und Modelling Framework in Software-Projekten tätig.
PartMaster GmbH
Lagerstraße 44/45
18055 Rostock
fon +49 381-20373995
fax +49 381-20373994
email info@partmaster.de
In den vorherigen Teilen dieser Blog-Serie sind zwei zentrale Probleme offen geblieben: Die Entkopplung des Controllers von UI-Frameworks wie SWT, Swing oder Android mittels des IObservableValue-Interfaces aus dem Eclipse Data Binding funktioniert sehr gut für die Properties der einfachen Widgets. Für komplexere Viewer (z.B. Tree- und TableViewer) und für Event-Listener (z.B. Mouse- und KeyListener) ist noch etwas Aufwand erforderlich, um die Entkopplung umzusetzen. In diesem Teil soll eine Lösung für das Problem der Entkopplung der Event-Listener vorgestellt werden.
Angenommen ein Klicken eines Push-Buttons soll den Aufruf eines Services auslösen. Das Auslösen eines Click-Events in der View soll also an den Aufruf eines Service-Methode im Controller gebunden werden. Normalerweise meldet der Controller dafür einfach einen ActionListener am Push-Buttons an. Die ActionListener-Klasse ist Bestandteil des UI-Frameworks. Unser Ziel ist es, den Controller unabhängig vom UI-Framework zu halten, darum brauchen wir eine andere Lösung. Das Eclipse Data Binding bietet für diesen Anwendungsfall leider keine Unterstützung, es kann nur Widget-Properties an Modell-Properties binden. Bei View-Events, die zu keiner Widget-Property-Änderung führen (z.B. dem Click-Event eines Push-Buttons), hilft das Data Binding nicht weiter.
Hier nun eine einfache Lösung für das Problem: Der Controller definiert ein Interface, in welchem für alle relevanten View-Events Handler-Methoden spezifiziert werden.
interface MyController {
void doCancel();
// ...
}
Listing 1: Controller-Interface mit Handler-Methode
Die View hat bereits ein Interface, mit welchem dem Controller der Zugriff auf die ObservableValues ermöglicht wird. Dieses View-Interface wird um eine Methode erweitert, mit der ein Controller-Interface bei der View registriert werden kann.
interface MyView {
// ...
void setController(MyController value);
}
Listing 2: View-Interface mit Methode zum Registrieren des Controllers
Die View-Implementierung registriert an ihren Widgets interne Event-Listener für die relevanten Events und ruft beim Auslösen des Events die entprechende Methode der registrierten Controller-Instanz auf.
public class MyViewImpl extends Composite implements MyView {
private MyControler controller;
private Button cancelButton;
// ..
public MyViewImpl(Composite parent) {
super(parent, SWT.NONE);
helpButton = new Button(this, SWT.PUSH);
helpButton.addSelectionListener(new SelectionListener() {
public void widgetSelectet(SelectionEvent event) {
controller.doCancel();
}
});
public void setController(MyController value) {
controller = value;
}
}
Listing 3: View-Implementierung delegiert Button-Click an Controller-Handler-Methode
Die Controller-Implementierung führt innerhalb der Handler-Methode den entsprechenden Service aus.
public class MyControllerImpl implements MyController {
public void doCancel() {
// ..
}
// ..
}
Listing 4: Controller-Implementierung implementiert Handler-Methode