MVP и пакетный цикл между представителем и докладчиком
Я только что пришел на проект, где они используют дизайн GWT и MVP. Они используют следующую структуру:
client.mvp.presenter (contains interfaces)
client.mvp.presenter.impl
client.mvp.view (contains interfaces)
client.mvp.view.impl
В коде Presenter знает свое представление, но представление также знает своего Presenter, поэтому я нашел циклы в пакете между Presenter.impl и View.impl.
Думая об этом снова, я спросил себя, почему impl
связаны между собой, вместо того, чтобы ссылаться только на интерфейсы и, таким образом, избегая цикла.
Но я также думаю, "почему представление должно знать своего предъявителя?" и, глядя на какой-то сайт, говорящий о MVP, не очень понятно, должны ли зрители и докладчики знать друг друга.
Что будет лучше?
- Попросить их использовать интерфейсы для удаления цикла?
- Попросить удалить
presenter
и позволяет ли ведущий непосредственно взаимодействовать с пользователем? - Ничего не делать, обычно цикл между этими пакетами в MVP
Спасибо!
2 ответа
С MVP докладчик и представление должны знать интерфейсы партнера:
- Ведущий обычно должен обновить представление
- Представление вызывает методы презентатора, когда происходят события (например, ValueChangeEvents).
Попросить их использовать интерфейсы для удаления цикла?
Да.
Попросить убрать докладчика с поля зрения и позволить докладчику непосредственно взаимодействовать с пользователем?
Нет, это не будет MVP.
Ничего не делать, обычно цикл между этими пакетами в MVP
Цикл, который обязательно остается, - это цикл создания: вы не можете использовать как презентатора в качестве параметра конструктора представления, так и представления в качестве конструктора параметра презентатора. Это становится особенно очевидным при использовании Dependency Injection на основе конструктора и теоретически неизбежно в Java. Но вы можете выбрать либо использовать установщик (по крайней мере на одной стороне), либо использовать фабрику / провайдера с внедрением конструктора.
На самом деле, в то время как презентатор impl [1] теперь нуждается в представлении (интерфейсе), интерфейс презентатора вообще не нужен.
Типичная картина:
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);
}
}
На самом деле, я обычно объявляю интерфейс презентатора, вложенный в интерфейс представления:
interface FooView extends IsWidget {
interface Presenter {
// ...
}
void setPresenter(Presenter presenter);
// ...
}
class FooPresenter extends AbstractActivity implements FooView.Presenter {
// ...
}
Что касается знания, подразумевается, что наиболее важно то, что презентатор не ссылается на представление, так как это (как правило) предотвратит юнит-тестирование без GWTTestCase
(издевается над видом). Обратное - меньше проблем, но тогда вам не нужен интерфейс презентатора по сравнению с Impl, верно?
[1] технически это может быть подразумеваемое представление, но, как правило, все наоборот, так что представление может пережить презентатора (презентаторы, как правило, легковесны, в отличие от представлений, которые могут иметь немалое время создания из-за манипуляций с DOM)