简体   繁体   中英

MVP and Package Cycle between view and presenter

I just came on a project where they use GWT and MVP design. They use the following structure:

client.mvp.presenter (contains interfaces)
client.mvp.presenter.impl
client.mvp.view (contains interfaces)
client.mvp.view.impl

In the code, the Presenter knows its view but the view also knows its presenter, so I found cycles in package between presenter.impl and view.impl

Thinking about that again, I asked myself why the impl linked themselves instead of referring to the interfaces only and so avoiding cycle.

But I also though "why should the view know its presenter ?" and looking some site talking about MVP its not that clear if view and presenter should know each other.

What would be best?

  • Ask them to use interfaces to remove cycle ?
  • Ask to remove presenter from view and let presenter handle directly user interaction?
  • Do nothing, it's usual to have cycle between those packages in MVP

Thanks !

Actually, while the presenter impl [1] needs to now the view (interface), the presenter interface generally doesn't.

The typical pattern is:

interface FooPresenter {
   // methods called by the view (generally in response to user interaction)
   void doSomething(String foo);
}

interface FooView {
   /** Tells the view which presenter instance to call back. */
   void setPresenter(FooPresenter presenter);

   // methods called by the presenter to control the view
   void showSomething(String foo);
}

class FooPresenterImpl implements FooPresenter {
    private final FooView view;

    FooPresenterImpl(FooView view, /* other dependencies here */) {
       this.view = view;
    }

    // could also be the start() method of com.google.gwt.activity.shared.Activity
    public void init() {
       view.setPresenter(this);
    }

    // optional; could be called from onStop() and onCancel() if using Activity
    public void dispose() {
       view.setPresenter(null);
    }
}

Actually, I generally declare the presenter interface nested within the view interface:

interface FooView extends IsWidget {

    interface Presenter {
       // ...
    }

    void setPresenter(Presenter presenter);

    // ...
}

class FooPresenter extends AbstractActivity implements FooView.Presenter {
   // ...
}

Wrt impls knowing impls, what's most important is that the presenter impl doesn't references the view impl, as it would (generally) prevent unit-testing it without a GWTTestCase (mocking the view). The reverse is less of a problem, but then you don't really need a presenter interface vs. impl, right?

[1] it could technically be the view impl, but it's generally the reverse, so that the view can outlive the presenter (presenters are generally lightweight, contrary to views, which can have a non-negligible creation time due to DOM manipulations)

With MVP, the presenter and view need to know the counterpart interfaces :

  • The presenter usually needs to update the view
  • The view calls presenter methods when events (eg ValueChangeEvents) occur.

Ask them to use interfaces to remove cycle ?

Yes.

Ask to remove presenter from view and let presenter handle directly user interaction?

No, that wouldn't be MVP.

Do nothing, it's usual to have cycle between those packages in MVP

The cycle that necessarily remains is the cycle on instantiation: You can't have both the presenter as a constructor param of the view and the view as a constructor param of the presenter. This becomes especially obvious with constructor based Dependency Injection, and is theoretically unavoidable in Java. But you can choose to either use a setter (on at least one side), or to use a factory/ provider with constructor injection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM