Согласно описанию Мартина Фаулера о MVP ( http://martinfowler.com/eaaDev/uiArchs.html )
Фаулер говорит о части MVC «Вид»:
Первым элементом Potel является обработка представления как структуры виджетов, виджетов, которые соответствуют элементам управления модели Forms и Controls, и удаление любого разделения представления / контроллера. Представление MVP является структурой этих виджетов. Он не содержит поведения, которое описывает, как виджеты реагируют на взаимодействие с пользователем .
(Жирный упор мой)
Затем от ведущего:
Активная реакция на действия пользователя живет в отдельном объекте презентатора. Фундаментальные обработчики пользовательских жестов все еще существуют в виджетах, но эти обработчики просто передают управление докладчику .
Затем докладчик решает, как реагировать на событие. Потель обсуждает это взаимодействие в первую очередь с точки зрения действий над моделью, которые он выполняет с помощью системы команд и выборов. Здесь полезно отметить подход, заключающийся в упаковке всех правок модели в команду - это обеспечивает хорошую основу для обеспечения поведения отмены / повтора.
(Опять жирный акцент мой)
Таким образом, в соответствии с рекомендациями Фаулера, ваш Просмотр не должен нести ответственность за любое поведение в ответ на событие кнопки; который включает в себя создание экземпляра UserInfo. Ответственность за принятие решения о создании объекта принадлежит методу Presenter, которому перенаправляется событие пользовательского интерфейса.
Однако можно также утверждать, что обработчик события кнопки View также не должен отвечать за передачу содержимого вашего элемента textView, поскольку View должен просто пересылать событие кнопки в Presenter и ничего более.
В MVP для представления обычно реализован интерфейс, который может использовать докладчик для получения данных непосредственно из представления (при этом гарантируя, что докладчик по-прежнему не зависит от самого представления). Так как UserInfo является простым POJO, это может быть справедливо для вида , чтобы выставить геттер для UserInfo которой ведущий может забрать Фрон View через интерфейс.
// The view would implement IView
public interface IView {
public UserInfo GetUserInfo();
}
// Presenter
public class AddUserPresenter {
private IView addUserView;
public void SetView(IView view) {
addUserView = view
}
public void onSomethingClicked() {
UserInfo userInfo = addUserView.GetUserInfo();
// etc.
}
}
Чем это отличается от передачи UserInfoнепосредственно в представление с помощью обработчика событий? Основное отличие состоит в том, что докладчик по-прежнему несет конечную ответственность за логику, которая вызывает создание UserInfoобъекта. то есть событие достигло докладчика до его создания UserInfo, что позволяет докладчику принять решение.
Представьте себе сценарий, в котором у вас была логика презентатора, в которой вы не хотели, UserInfoчтобы она создавалась на основе некоторого состояния в представлении. Например, если пользователь не установил флажок в представлении или вы проверили проверку по некоторому полю, которое было добавлено в UserInfo, но не удалось - ваш докладчик может содержать дополнительную проверку перед вызовом GetUserInfo- т.е.
private boolean IsUsernameValid() {
String username = addUserView.GetUsername();
return (username != null && !username.isEmpty());
}
public void onSomethingClicked() {
if (IsUsernameValid()) {
UserInfo userInfo = addUserView.GetUserInfo();
// etc.
}
}
Эта логика остается внутри презентатора, и ее не нужно добавлять в представление. Если бы представление отвечало за вызов, GetUserInfo()то оно также отвечало бы за любую логику, окружающую его использование; это то, что пытается избежать шаблон MVP.
Таким образом, хотя метод, который создает, который UserInfoможет физически существовать в классе View, он никогда не вызывается из класса View, только из Presenter.
Конечно, если создание в UserInfoконечном итоге требует дополнительных проверок содержимого пользовательских виджетов ввода (например, преобразование строк, проверка и т. Д.), То было бы лучше выставить отдельные средства получения для этих вещей, чтобы проверка / преобразование строк могло занять место внутри докладчика - и тогда докладчик создает свой UserInfo.
В целом, вашей главной целью в отношении разделения между Presenter / View является обеспечение того, чтобы вам никогда не приходилось писать логику в представлении. Если вам когда-либо понадобится добавить ifоператор по какой-либо причине (даже если это ifоператор относительно состояния свойства виджета - проверка пустого текстового поля или логическое значение для флажка), то он принадлежит представителю.
onSomethingClicked(), чтобы, когда пользователь нажимает «что-то», вызывается Viewpresenter.onSomethingClicked()? Или мои методы презентатора должны быть названы как предполагаемые действия, в моем случаеaddUser()?