简体   繁体   English

视图和演示者之间的MVP和打包周期

[英]MVP and Package Cycle between view and presenter

I just came on a project where they use GWT and MVP design. 我刚参加了一个使用GWT和MVP设计的项目。 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 在代码中,Presenter知道其视图,但该视图也知道其Presenter,因此我在presenter.impl和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. 再三考虑,我问自己为什么impl链接自己而不是仅引用接口,从而避免了循环。

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. 并查看一些谈论MVP的站点,不清楚视图和演示者是否应该彼此了解。

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? 要求从视图中删除presenter ,让演示者直接处理用户交互?
  • Do nothing, it's usual to have cycle between those packages in MVP 不执行任何操作,通常在MVP中的这些程序包之间循环

Thanks ! 谢谢 !

Actually, while the presenter impl [1] needs to now the view (interface), the presenter interface generally doesn't. 实际上,虽然主持人impl [1]现在需要视图(界面),但主持人界面通常不需要。

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: 实际上,我通常将presenter接口声明为嵌套在view接口中:

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). Wrt表示知道impls,最重要的是演示者impl不引用视图impl,因为(通常)它将防止在没有GWTTestCase情况下对它进行单元测试(模拟视图)。 The reverse is less of a problem, but then you don't really need a presenter interface vs. impl, right? 反之则不成问题,但是与impl相比,您实际上并不需要presenter接口,对吗?

[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) [1]从技术上讲,它可能是视图隐含的,但通常是相反的,因此视图可以超过演示者的寿命(演示者通常是轻量级的,与视图相反,由于DOM操作,视图的创建时间不可忽略)

With MVP, the presenter and view need to know the counterpart interfaces : 使用MVP,演示者和视图需要了解对应的接口

  • The presenter usually needs to update the view 演示者通常需要更新视图
  • The view calls presenter methods when events (eg ValueChangeEvents) occur. 当事件(例如ValueChangeEvents)发生时,视图将调用presenter方法。

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. 不,那不是MVP。

Do nothing, it's usual to have cycle between those packages in MVP 不执行任何操作,通常在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. 那一定是剩下的周期是实例化循环:你不能兼得演示作为视图的构造PARAM 视图作为主持人的构造PARAM。 This becomes especially obvious with constructor based Dependency Injection, and is theoretically unavoidable in Java. 这在基于构造函数的依赖注入中尤其明显,并且在Java中理论上是不可避免的。 But you can choose to either use a setter (on at least one side), or to use a factory/ provider with constructor injection. 但是您可以选择使用设置器(至少在一侧),或使用带有构造函数注入的工厂/ 提供程序

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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