В MVC может ли несколько представлений иметь один и тот же контроллер или одно представление должно иметь один уникальный контроллер?

15

У меня есть несколько вопросов при разработке архитектуры для проекта вокруг MVC. (Это проект C ++ / Marmalade SDK, я не использую какой-либо конкретный MVC-фреймворк, я его создаю.)

В нескольких статьях (например, в оригинальной статье Стива Бурбека ) я продолжаю читать концепцию «Триада MVC», которая поражает меня, так как я воспринял эту концепцию довольно буквально. Когда я прочитал его, в первый раз выглядело, как будто приложение построено на единицах «триады MVC» - по одному для каждого элемента пользовательского интерфейса, который я предположил, - но я нахожу это довольно негибким, и я думаю, что MVC не предназначен для использования. Затем, продолжая исследование этой проблемы, я обнаружил несколько примеров тесной связи контроллера и представления, а именно отношения 1-к-1 - TextEditView имеет TextEditController.

Но когда я возвращаюсь к своему проекту, я обнаружил, что было бы полезно иметь один контроллер (с помощью «логической единицы», такой как AddElementController) и несколько представлений для этого конкретного контроллера.

Я четко думаю о чем-то вроде AddElementController, который должен иметь своего рода интерфейс с вкладками. Должен ли я иметь AddElementController, который имеет AddElementTabView и несколько AddImageView, AddSoundView и т. Д. Для вкладок? Или у меня должен быть отдельный «субконтроллер» для каждого вида вкладок?

В целом, и в отношении паттерна MVC (а не специфического понимания / реализации этого фреймворка X), правильно ли иметь несколько представлений для контроллера, или у каждого представления должен быть свой конкретный контроллер?

Кроме того, правильно ли хранить некоторую информацию о состоянии на контроллере или она должна быть без сохранения состояния (это означает, что состояние должно быть помещено в некоторую модель состояния, не относящуюся к домену)?

Спасибо всем заранее.

pedrosanta
источник

Ответы:

14

Проблема в том, что шаблон MVC был разработан в системе, которая на самом деле больше не существует. Он был изобретен в Smalltalk в то время, когда библиотеки пользовательского интерфейса еще не существовали. Чтобы создать диалоговое окно, вы нарисовали все поля, выделили соответствующие квадраты, убедились, что текст, который вы рисуете, оказался в нужном месте ... и т. Д.

Представьте, что было бы, если бы вы написали диалоговое приложение, используя только один большой холст. Это мир, из которого исходит MVC.

«Представлением» в этой системе было текстовое поле, и это был класс, который отвечал за рисование поля, текста, рисование выделенных областей, реагирование на изменения в тексте и т. Д.

«Контроллер» был другим классом, который принимал события мыши, происходящие внутри этого поля, такие как перемещение мыши, нажатие клавиши, нажатие клавиши вверх, щелчки и т. Д., И он решал, что произошло. Должны ли мы изменить текст? Должны ли мы изменить выбор? Вроде того.

«Модель» была еще одним классом, который представлял основные данные и состояние компонента. Модель текстового поля будет иметь текст, шрифт, выделение и т. Д.

Как вы можете видеть, в такой ситуации три компонента очень запутаны в представлении одной идеи. В этом контексте имеет смысл говорить о «триаде».

Сегодня, если вы работаете над созданием библиотеки пользовательского интерфейса и используете необработанные команды рисования, вы можете сделать что-то подобное. Но применение паттерна «MVC» вышло за рамки его первоначальной цели. Сейчас у вас есть «представление», которое на самом деле может быть полным диалогом, и контроллер, который реагирует на такие события, как «textChanged» или «buttonClicked». Модель в сегодняшнем MVC обычно является чем-то довольно отсоединенным от системы (но, как правило, связанным с представлением, предоставляя некоторый интерфейс наблюдателя), и может быть много представлений, связанных с одной моделью.

Например, в системе, которую я недавно спроектировал, у нас было более 10 просмотров, каждый из которых наблюдал за одним «держателем» документа и его активным документом. Основной интерфейс чертежа взаимодействовал с макетом документа, различными представлениями свойств, которые наблюдали за выбранным элементом и обеспечивали интерфейс записи, и уменьшенным масштабом представления основного вида, в котором отображался весь документ, а не только видимое окно. Некоторые из этих представлений имели контроллеры различной сложности, которые превращали события графического интерфейса в изменения в документе, что в свою очередь уведомляло бы его различные представления.

Можно ли еще назвать такие отношения "триадой"? Возможно, но я думаю, что это подразумевает слишком многое из прежнего, более старого приложения MVC.

Не могли бы вы поделиться контроллерами с разными взглядами? Зависит от того, насколько похожи взгляды. Я обнаружил, что, вообще говоря, этот тип объекта имеет поведение, специфичное для представления, которым он управляет, И модель, которой он манипулирует, чтобы быть очень многократно используемой ... но всегда есть исключения.

Эдвард Стрендж
источник
5

По-разному. Существует несколько вариантов MVC, в некоторых из которых имеет смысл только соотношение 1: 1 (например, «скромное диалоговое окно»), в других - нет. Я бы порекомендовал прочитать серию статей « Построй свою собственную CAB », в которых объясняются наиболее важные варианты MVC.

Док Браун
источник
3

Представления не имеют контроллеров в MVC. Контроллер является боссом, поэтому Контроллер решает, какое представление будет отображено, и представления не заботятся о том, какой контроллер запросил представление.

Вы можете / будете иметь несколько видов из контроллера. Просто подумайте о создании модели для каждого вида, если вы хотите придерживаться шаблона MVC.

Мерт Акчакая
источник
3

Задача контроллера - контролировать взаимодействие пользователя с моделью вашего домена, то есть это уровень косвенности между тем, что видит пользователь (представление), и состоянием ваших приложений (модель).

Когда пользователь делает запрос, он направляется в контроллер. Контроллер решает, как передать этот запрос приложению, обычно через какой-то класс обслуживания. Затем он интерпретирует ответ от этого класса обслуживания и решает, какое представление отправить пользователю.

Контроллер может всегда возвращать одно и то же представление (1: 1), если пользователь может сделать только один вид запроса контроллера, и он всегда требует одинакового ответа. Например, HelloWorldControllerвсегда будет HelloWorldViewотображаться «Hello, World!»

С другой стороны, контроллеру часто приходится выбирать разные виды, в зависимости от того, что говорит модель. TeamRosterControllerМожет возвращать RugbyTeamRosterViewили FootbalTeamRosterView, в зависимости от типа команды запрашивали.

Обычно предпочтительно, чтобы контроллеры не имели состояния, хотя некоторый доступ к состоянию сеанса пользователя может быть необходимым или желательным. Вы должны управлять доступом к этому состоянию отдельно, если это возможно.

Я настоятельно рекомендую взглянуть на реальную среду MVC, чтобы увидеть, что она делает и как она работает. Вам не нужно его использовать, но вы определенно получите лучшее понимание, прежде чем создавать свой собственный.

Мэтью Флинн
источник