My application uses a simple Model-View-Presenter architecture and uses the following classes and interface:
Presenter:
public abstract class Presenter<V> { private V view; public final void setView(V view) { this.view = view; } protected final V getView() { return this.view; }}
View
public abstract class View<V, P extends Presenter<V>> implements ViewAdapter<V> { private final P presenter; public View(P presenter) { this.presenter = presenter; } protected final P getPresenter() { return this.presenter; } void initialize() { this.getPresenter().setView(this.asView()); }}
ViewAdapter
interface ViewAdapter<T> { T asView();}
The application is then wired up like this:
- A concrete
Presenter
is created. - A concrete
View
is created, passing in the concretePresenter
as a constructor parameter. - The
View
is initialised. During initialisation, theView
calls theasView
method to pass a view instance to the presenter.
Each concrete presenter in the application is parameterised with a view interface. Each concrete view class implements a view interface and can then pass itself to the presenter during initialisation and it is in this area that I am looking for advice.
The ViewAdapter
interface exists solely to allow the concrete view to pass itself to the presenter via the asView
method whilst maintaining type safety. My concrete views which derive from the View class are then forced to provide an implementation of the asView
method in order to provide a view instance to the presenter that is of the correct type.
Every implementation looks the same:
@Overridepublic FooView asView() { return this; // this implements the FooView interface.}
All this basically does is force 'this' to implement FooView
as I am unable to express something like this:
// Example, not valid code, won't compile!public abstract class View<V, P extends Presenter<V>> implements V {}
Which would allow me to remove the ViewAdapter
interface and pass the view to the presenter in the abstract View
class like this, removing the redundancy:
void initialize() { this.getPresenter().setView(this);}