В прошлом я использовал MVP и MVC, и я предпочитаю MVP, так как, на мой взгляд, он намного лучше контролирует ход выполнения.
Я создал свою инфраструктуру (классы хранилища данных / репозитория) и без проблем использую их при жестком кодировании примеров данных, поэтому теперь я перехожу к графическому интерфейсу и готовлю свой MVP.
Раздел А
Я видел, как MVP использует представление в качестве точки входа, то есть в методе конструктора представлений он создает презентатор, который, в свою очередь, создает модель, связывая события по мере необходимости.
Я также видел презентатора как точку входа, где создаются представление, модель и презентатор, а затем этот презентатор получает объект представления и модели в своем конструкторе для связывания событий.
Как и в 2, но модель не передается ведущему. Вместо этого модель является статическим классом, где методы вызываются и ответы возвращаются напрямую.
Раздел Б
С точки зрения поддержания представления и модели в синхронизации я видел.
Всякий раз, когда значение в представлении изменяется, то есть
TextChanged
событие в .Net / C #. Это запускает объект,DataChangedEvent
который передается в модель, чтобы постоянно поддерживать его синхронизацию. И там, где модель изменяется, то есть фоновое событие, которое она слушает, тогда представление обновляется с помощью той же идеи подъемаDataChangedEvent
. Когда пользователь хочет зафиксировать изменения,SaveEvent
он срабатывает, передаваясь в модель для сохранения. В этом случае модель имитирует данные представления и обрабатывает действия.Аналогично # b1, однако представление не синхронизируется с моделью все время. Вместо этого, когда пользователь хочет зафиксировать изменения,
SaveEvent
он увольняется, и докладчик берет последние детали и передает их в модель. в этом случае модель не знает о данных представлений, пока не потребуется воздействовать на них, и в этом случае передаются все необходимые детали.
Раздел С
Отображение бизнес-объектов в представлении, т.е. объект (MyClass), не примитивные данные (int, double)
Представление имеет поля свойств для всех своих данных, которые будут отображаться как доменные / бизнес-объекты. Например,
view.Animals
предоставляетIEnumerable<IAnimal>
свойство, даже если представление обрабатывает их в узлах в TreeView. Тогда для выбранного животного это выставитSelectedAnimal
какIAnimal
собственность.Представление не знает об объектах домена, оно предоставляет свойство только для типов объектов, включенных в примитивы / рамки (.Net / Java). В этом случае презентатор передает объект адаптера объекту домена, затем адаптер преобразует данный бизнес-объект в элементы управления, видимые в представлении. В этом случае адаптер должен иметь доступ к фактическим элементам управления в представлении, а не только к любому представлению, поэтому он становится более тесно связанным.
Раздел D
Несколько представлений используются для создания одного элемента управления. т.е. у вас сложный вид с простой моделью, такой как сохранение объектов разных типов. У вас может быть система меню сбоку, при каждом щелчке на элементе отображаются соответствующие элементы управления.
Вы создаете одно огромное представление, которое содержит все отдельные элементы управления, которые предоставляются через интерфейс представлений.
У вас есть несколько просмотров. У вас есть один вид для меню и пустой панели. Это представление создает другие необходимые представления, но не отображает их (visible = false), это представление также реализует интерфейс для каждого представления, которое оно содержит (т. Е. Дочерние представления), поэтому оно может быть доступно одному докладчику. Пустая панель заполнена другими видами (
Controls.Add(myview)
) и ((myview.visible = true
). События, возникающие в этих «дочерних» представлениях, обрабатываются родительским представлением, которое, в свою очередь, передает событие докладчику, и наоборот, для передачи событий обратно дочерним элементам.Каждый вид, будь то основной родительский или меньший дочерний вид, каждый связан с их собственным презентатором и моделью. Вы можете буквально просто перетащить элемент управления представлением в существующую форму, и он будет иметь готовую функциональность, просто нужно подключиться к докладчику за кулисами.
Раздел Е
Если у всех есть интерфейс, теперь основанный на том, как MVP сделан в вышеприведенных примерах, повлияет на этот ответ, поскольку они могут быть несовместимыми.
У всего есть интерфейс, представление, презентатор и модель. Каждый из них, очевидно, имеет конкретную реализацию. Даже если у вас есть только один конкретный вид, модель и ведущий.
Вид и Модель имеют интерфейс. Это позволяет взглядам и моделям отличаться. Презентатор создает / получает вид и моделирует объекты, и он просто служит для передачи сообщений между ними.
Только вид имеет интерфейс. Модель имеет статические методы и не создается, поэтому нет необходимости в интерфейсе. Если вам нужна другая модель, докладчик вызывает другой набор статических методов класса. Будучи статичной, Модель не имеет ссылки на докладчика.
Личные мысли
Из всех различных вариантов, которые я представил (большинство я, вероятно, использовал в той или иной форме), которые, я уверен, есть и другие. Я предпочитаю A3, так как бизнес-логику можно использовать многократно за пределами MVP, B2 - для меньшего дублирования данных и меньшего количества инициируемых событий. C1, чтобы не добавлять в другой класс, конечно, он помещает небольшое количество логики, не поддающейся проверке, в представление (как визуализируется объект домена), но это может быть проверено кодом или просто просмотрено в приложении. Если бы логика была сложной, я бы согласился на класс адаптера, но не во всех случаях. Для раздела D я чувствую, что D1 создает представление, которое слишком велико по крайней мере для примера меню. Я использовал D2 и D3 раньше. Проблема с D2 заключается в том, что вам приходится писать много кода для маршрутизации событий от докладчика к правильному дочернему представлению, а он не совместим с перетаскиванием, каждому новому элементу управления требуется больше проводки для поддержки одного докладчика. D3 - мой предпочтительный выбор, но он добавляет еще больше классов в качестве докладчиков и моделей для работы с представлением, даже если представление оказывается очень простым или не нуждается в повторном использовании. Я думаю, что смесь D2 и D3 лучше всего зависит от обстоятельств. Что касается раздела E, я думаю, что все, что имеет интерфейс, может быть излишним, я уже делаю это для доменных / бизнес-объектов и часто не вижу в этом «никакого преимущества» в «дизайне», но это помогает при проверке объектов в тестах. Лично я бы видел E2 как классическое решение, хотя видел, как E3 использовался в 2 проектах, над которыми я работал ранее. Я думаю, что смесь D2 и D3 лучше всего зависит от обстоятельств. Что касается раздела E, я думаю, что все, что имеет интерфейс, может быть излишним, я уже делаю это для доменных / бизнес-объектов и часто не вижу в этом «никакого преимущества» в «дизайне», но это помогает при проверке объектов в тестах. Лично я бы видел E2 как классическое решение, хотя видел, как E3 использовался в 2 проектах, над которыми я работал ранее. Я думаю, что смесь D2 и D3 лучше всего зависит от обстоятельств. Что касается раздела E, я думаю, что все, что имеет интерфейс, может быть излишним, я уже делаю это для доменных / бизнес-объектов и часто не вижу в этом «никакого преимущества» в «дизайне», но это помогает при проверке объектов в тестах. Лично я бы видел E2 как классическое решение, хотя видел, как E3 использовался в 2 проектах, над которыми я работал ранее.
Вопрос
Я правильно внедряю MVP? Есть ли правильный способ сделать это?
Я читал работу Мартина Фаулера, в которой есть вариации, и я помню, когда я впервые начал заниматься MVC, я понял концепцию, но изначально не мог понять, где находится точка входа, у всего есть своя функция, но что контролирует и создает оригинал набор объектов MVC.
источник
Ответы:
Многое из того, что вы здесь представляете, очень разумно и обоснованно. Некоторые из вариантов будут зависеть от специфики приложения и от того, какой из них будет «правильным». Как и в большинстве случаев, правильного ответа не будет. Некоторые из вариантов здесь будут иметь смысл, и эти варианты могут быть совершенно неверными для следующего применения и обстоятельств. Не зная некоторых особенностей приложения, я думаю, что вы на правильном пути и приняли некоторые здравые, вдумчивые решения.
Для меня, я чувствую, что ведущий почти всегда должен быть отправной точкой. Наличие пользовательского интерфейса в качестве точки входа создает слишком много логики в пользовательском интерфейсе и лишает его возможности заменять новый пользовательский интерфейс без больших изменений в коде. И действительно, это работа докладчика.
источник
Мы используем модифицированную форму MVP в нашем приложении .NET 2.0 Winforms. Нам не хватало двух частей: модифицированного адаптера WPF ViewModel и добавления привязки данных. Наш специфический образец - MVPVM.
Мы подключаемся в качестве первого докладчика почти во всех случаях, за исключением пользовательских пользовательских элементов управления, которые подключены в виде первого для удобства дизайнеров. Мы используем внедрение зависимостей, генерируемые кодом ViewModels, BDD для докладчиков и TDD / TED для модели.
Виртуальные машины - это просто массивный плоский набор свойств, которые вызывают PropertyChanged при их изменении. Было очень легко сгенерировать их с помощью кода (и связанных с ними тренировочных юнит-тестов). Мы используем их для чтения и записи в интерактивные элементы управления, а также для управления включенными состояниями. ViewModel связан с View, так как мы используем привязку данных почти все остальное.
Иногда в представлении будут методы для выполнения задач, которые виртуальная машина не может выполнить. Это обычно контролирует видимость элементов (WinForms может быть требователен) и вещи, которые отказываются быть привязанными к данным. Представление всегда предоставляет такие события, как «Логин» или «Перезапуск», с соответствующими EventArgs, чтобы воздействовать на поведение пользователя. Если нам не пришлось использовать хак, такой как «View.ShowLoginBox», представление полностью взаимозаменяемо, если оно соответствует общим требованиям дизайна.
Нам потребовалось около 6-8 месяцев, чтобы закрепить этот шаблон. У него много частей, но он очень гибкий и чрезвычайно мощный. Наша конкретная реализация является очень асинхронной и управляемой событиями, которая может быть просто артефактом других требований, а не побочным эффектом поведения проекта. Например, я добавил синхронизацию потоков в базовый класс, от которого унаследована наша виртуальная машина (который просто предоставил метод OnPropertyChanged для вызова события) - и poof, теперь у нас могут быть многопоточные презентаторы и модели.
источник
Я использую версию PureMvc, которая была модифицирована для .Net, а затем расширена мной.
Я привык к использованию PureMvc в приложениях Flex. Это базовый тип фреймворка, поэтому его довольно легко адаптировать, если вы хотите настроить его.
Я взял следующие вольности с этим:
В PureMvc вы можете использовать команду в качестве точки входа, типичная команда Start настроит модель в максимально возможной степени, затем создаст MainForm, создаст и зарегистрирует посредник для этой формы и с этой формой, а затем сделает Application.Run. на форме.
Посредник для формы будет отвечать за настройку всех суб-посредников, некоторые из них могут быть автоматизированы, опять же, с помощью трюков отражения.
Система, которую я использую, совместима с перетаскиванием, если я понимаю ваше значение. Фактическая форма все создается в VS, но мой опыт только с формами, которые имеют статически созданные элементы управления. Такие вещи, как динамически создаваемые пункты меню, кажутся выполнимыми с небольшой настройкой посредника для этого меню или подменю. Это может стать проблемой, когда посредник не имеет статического корневого элемента, к которому можно подключиться, и вы попадаете в создание динамических посредников «экземпляра».
источник