Über Steffen Nowacki

Bild des Benutzers Steffen Nowacki

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

Entkopplung des Controllers von den GUI-Framework-Events

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.

Das Problem

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.

Die Lösung

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