Подтвердить что ты не робот

Понимание шаблона MVC

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

Из того, что я понял, View - это то, что видит пользователь. Так что это обычно окно/форма. Controller находится в промежутке между View и Model. Контроллер будет передавать данные "поток" в обоих направлениях. Он также будет сохраняться в случае необходимости (если у меня есть мастер с 5 шагами, это отвечает Controller, чтобы убедиться, что они сделаны в правильном порядке и т.д.). Model, - это то место, где живет ядро ​​моей логики приложения.

Правильно ли это мнение?

Чтобы попытаться превратить это во что-то более значимое, я попытаюсь набросать простой пример с WinForms (без ASP.NET или WPF, пожалуйста!) в толпу java, из того, что я понял, Swing работает аналогично WinForms!), чтобы узнать, правильно ли я это сделаю, и я буду поднимать вопросы, к которым я всегда прихожу, делая это.


Предположим, что у меня есть модель, содержащая только класс (просто чтобы это стало проще). Я знаю, что это сделает этот пример глупым, но тем более проще):

class MyNumbers {
    private IList<int> listOfNumbers = new List<int> { 1, 3, 5, 7, 9 };

    public IList<int> GetNumbers() {
        return new ReadOnlyCollection<int>(listOfNumbers);
    }
}

Теперь пришло время сделать мой Controller:

class Controller
{
    private MyNumbers myNumbers = new MyNumbers();

    public IList<int> GetNumbers() {
        return myNumbers.GetNumbers();
    }
}

View должен иметь только ListBox, который имеет в качестве элементов все числа, полученные в MyNumbers.

Теперь возникает первый вопрос:

Должен ли Controller отвечать за создание MyNumbers? В этом простом случае я считаю его приемлемым (как MyNumbers будет делать то же самое, независимо от того, что и не имеет связанного состояния). Но допустим, что я хотел бы использовать для всех разных контроллеров мое приложение имеет тот же экземпляр MyNumbers. Я должен был бы передать этому Controller (и всем остальным, кому это нужно) этот экземпляр MyNumbers, который я хочу использовать. Кто будет отвечать за это? В примерах WinForms это будет View? Или это будет класс, который создает View?

Обоснование вопроса: каков порядок создания этих трех частей? Что такое код, который вызвал "владелец" MVC для его создания? Должно ли Controller создавать как View, так и Model? Если View создает экземпляр Controller и Controller Model?

Второй вопрос:

Как должен выглядеть метод main, если я хочу, чтобы мое приложение имело Use Case этот Controller портрети?

Третье:

Почему на следующей диаграмме MVC View есть стрелка к Model? Должен ли Controller быть всегда мостом между View и Model?

alt text


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

Спасибо!

4b9b3361

Ответ 1

Самый простой способ получить дескриптор MVC - использовать его в рамках, которая обеспечивает его соблюдение.

  • Модель взаимодействует с источником данных (DB или любым другим) и предоставляет вам доступ к вашим данным.
  • Вид взаимодействует с внешним миром, он получает откуда-то вход и передает данные контроллеру, он также слушает контроллер, чтобы убедиться, что он отображает правильные данные.
  • Контроллер - это то, где происходит вся магия; контроллер управляет данными, толкает события и обрабатывает изменения в обоих направлениях (в/из представления и в/из модели).

Эта диаграмма очень полезна (она имеет гораздо больше смысла, чем Wikipedia): Диаграмма MVC http://java.sun.com/developer/technicalArticles/javase/mvc/images/Figure4.gif

Источник и отличная статья о MVC!

Ответ 2

Что касается критики в моем сообщении, я подумал, что буду опубликовать сообщение о том, как я склонен создавать шаблон MVC в PHP

В PHP я выкладываю фреймворк в несколько разделов, ведь некоторые из них являются нормальными, когда дело касается MVC.

Праймериз:

  • контроллер
  • Model
  • Вид

вторичности  - ModelLayer

  • ViewLoader
  • Библиотека
  • ErrorLayer

Внутри контроллера я обычно разрешаю всем доступ к вторичным слоям, а View и Model из Primary.

Вот как я его структурировал

|---------|       |------------|       |------------|
| Browser | ----> | Controller | ----> |   Model    |
|---------|       |------------|       |------------|
     |                  |   |                |
     |                  |   |----------------|
     |                  |
     |            |------------|
     -------------|    View    |
                  |------------|

Из моей диаграммы обычно обходите соединение View <-> Model и выполняем Controller <-> Model, а затем ссылка из Controller <-> View назначает данные.

В моих рамках я стараюсь создать систему хранения объектов, чтобы я мог легко извлекать объекты и т.д. пример моего хранилища объектов выглядит так:

class Registry
{
   static $storage = array();

   public static function get($key)
   {
       return isset(self::storage[$key]) ? self::storage[$key] : null;
   }

   public static function set($key,$object)
   {
       self::"storage[$key] = $object;
   }
}

Несколько более продвинутый, чем контур, поэтому при первом инициализации объектов я храню их как Registry::set("View",new View());, чтобы всегда было доступно.

Итак, в моем контроллере witch является базовым контроллером, я создаю несколько магических методов __get() __set(), так что любой класс, который расширяет контроллер, я могу легко вернуть запрос, например:

abstract class Controller
{
   public function __get($key)
   {
       //check to make sure key is ok for item such as View,Library etc

       return Registry::get($key); //Object / Null
   }
}

И пользовательский контроллер

class Controller_index extends Controller
{
    public function index()
    {
       $this->View->assign("key","value"); // Exucutes a method in the View class
    }
}

Модель также будет помещена в реестр, но разрешена только для вызова из ModelLayer

class Model_index extends ModelLayer_MySql
{
}

или

class Model_index extends ModelLayer_MySqli
{
}

или файловая система

class Model_file extends ModelLayer_FileSystem
{
}

чтобы каждый класс мог быть специфичным для типа хранилища.

Это не традиционный тип шаблона MVC, но его можно назвать Adoptive MVC.

Другие объекты, такие как View Loader, не должны помещаться в реестр, поскольку они специально не предназначены для пользователей, а используются другими объектами, такими как View

abstract class ViewLoader
{
   function __construct($file,$data) //send the file and data
   {
       //Include the file and set the data to a local variable
   }

   public function MakeUri()
   {
       return Registry::get('URITools')->CreateURIByArgs(func_get_args());
   }
}

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

Пример файла шаблона.

<html>
   <body>
      <?php $this->_include("another_tpl_file.php"); ?>
      <?php if(isset($this->session->admin)):?>

          <a href="<?php echo $this->MakeUri("user","admin","panel","id",$this->session->admin_uid) ?>"><?php echo $this->lang->admin->admin_link ?></a>

      <?php endif; ?>
   </body>
</html>

Я надеюсь, что мои примеры помогут вам понять это немного больше.

Ответ 3

Ответ на третий вопрос:

Когда модель изменяется, она уведомляет представление, затем представление получает данные из модели с использованием своих геттеров.

Ответ 4

"Из того, что я понял," вид "- это то, что видит пользователь. Таким образом, обычно это окно/форма. Контроллер находится между представлением и моделью. Контроллер будет" обрабатывать "данные в обоих направлениях. также сохраняйте состояние, когда это необходимо (если у меня есть мастер с 5 шагами, это отвечает Контроллеру, чтобы убедиться, что они сделаны в правильном порядке и т.д.). Модель - это то место, где живет ядро ​​моей логики приложения."

Это почти правильно. Контроллер не сохраняет данные. Он вызывает службу, которая сохраняет данные. Причина в том, что сохраняющиеся данные никогда не являются просто призывом к сохранению. Возможно, вам захочется выполнить проверки валидации данных, чтобы убедиться, что он является нормальным в соответствии с потребностями вашего бизнеса. Возможно, вы захотите выполнить некоторую аутентификацию, чтобы убедиться, что данные могут быть сохранены пользователем. Если вы делаете это в службе, то у вас есть хороший набор функций, которые вы можете использовать снова и снова, скажем, для webapp и веб-службы. Если вы сделаете это в контроллере, скажем, для веб-приложения, когда вы идете писать свой веб-сервис, вам придется реорганизовать и/или дублировать код.

В ответ на ваш комментарий "Я не уверен, что полностью понял ваш вопрос. Контролирует ли контроллер ввод пользовательского интерфейса, или это модель, которая это делает?"

Контроллер должен контролировать только те пути, которые выполняются бизнес-функциональностью. Это оно. Контроллеры должны быть самой простой частью кода для записи. Вы можете выполнить некоторую проверку на gui (т.е. Просмотр, например, например, правильное форматирование адресов электронной почты, текстовые входы не превышают максимумы), но бизнес-уровень также должен подтвердить ввод - по той причине, о которой я упоминал ранее, что когда вы начать стоять больше конечных точек, вам не нужно рефакторировать.

Ответ 5

Это от Java, но, надеюсь, это поможет.

Для основного:

public static void main(String[] args) 
{
       MyNumbers myNums = new MyNumbers();  // Create your Model
       // Create controller, send in Model reference.      
       Controller controller = new Controller(myNums); 
}

Вашему контроллеру нужна ссылка на вашу модель. В этом случае контроллер фактически создает все компоненты Swing. Для С# вы можете оставить здесь инициализацию формы, но View/Form нуждается в ссылке на Model (myNums) и Controller (контроллер). Надеюсь, некоторые люди С# могут помочь на этом фронте. Просмотр также должен регистрироваться как наблюдатель модели (см. Шаблон наблюдателя).

Вот конструктор, который у меня есть (скорректированный для вашего случая):

public NumberView(Controller controller, MyNumbers myNums)
{
      this.controller = controller; // You'll need a local variable for this
      this.myNums = myNums; //You'll need a local variable for this
      myNums.registerObserver(this); // This is where it registers itself
}

Вид передает работу Контроллеру для обработки действий пользователя (кнопок, что угодно). Контроллер решает, что нужно вызвать/сделать в модели. В общем, модель затем делает что-то и изменяет свое состояние (может быть, больше номеров в вашем списке). Как бы то ни было). В этом случае Модель позволит своим Наблюдателям знать, что она изменилась и обновилась. Затем открывается View и получает новые данные и обновляет сам. Вот почему Обсуждение модели и представления (ваш третий вопрос).

Итак, модель будет иметь:

public void notifyObservers()
{
    for (Observer o: observers)
    {
        o.update();  // this will call the View update below since it is an Observer
    }
}

Итак, в представлении у вас будет что-то вроде этого:

public void update()
{
    setListBox(myNums.getNumbers());  // Or whatever form update you want
}

Надеюсь, что это поможет. Я знаю, что это Java, но концепция по-прежнему применяется. Вам нужно будет немного почитать образец Observer, чтобы полностью его получить. Удачи!

Ответ 6

Должен ли Контролер быть ответственным для создания MyNumbers?

Я бы сказал "определенно нет".

Если шаблон MVC предназначен для развязки элементов M, V и C, как это может работать, если C просто создает экземпляр M с помощью new MyNumbers()?

В Java мы будем использовать что-то вроде Spring Framework здесь. Вам нужен способ выражения отношения зависимостей, а точнее подробностей его выполнения, в файле конфигурации или в другом подходящем месте (т.е. Не в компилированном коде).

Но есть еще один элемент этой проблемы: вы, вероятно, не должны определять переменную myNumbers (внутри C) с конкретным типом среды выполнения, который вы собираетесь использовать. Используйте интерфейс или абстрактный класс и оставьте его открытым относительно того, каков фактический тип среды выполнения. Таким образом, в будущем вы можете повторно реализовать интерфейс IMyNumbers для удовлетворения новых требований (те, которые вы не знаете сегодня), и ваш компонент C будет продолжать работать отлично, ни один более мудрый.

Ответ 7

Почему на следующей диаграмме MVC у View есть стрелка к модели? Должен ли контроллер всегда быть мостом между View и Model?

Это модель MVC 2. Вы можете видеть ее обычно в приложении Java-приложения где CONTROL выполняет бизнес, а также обрабатывает данные из/в MODEL и выбирает, какой VIEW отображать обратно клиенту. При рендеринге клиенту VIEW будет использовать данные из МОДЕЛИ:

alt text http://www.blogjava.net/images/blogjava_net/marco/7342/o_2.JPG

Ниже приведен пример доступа к данным из файла JSP (VIEW), который bean (MODEL):

class Person {String name;} // MODEL
My name is ${bean.name}     // VIEW

Ответ 8

Я постараюсь ответить на это с относительно менее технического стенда на то, что стоит. Я попробую пройти общий пример.

Controller управляет тем, что используется view. Итак, скажем, если вы пишете на страницу, Controller направит вас к input view (скажем), а если вы читаете ту же страницу, он направит вас к ней success view (скажем).

После записи на страницу Controller передаст эти параметры соответствующему model, где находится логика, относящаяся к тому, что должно быть сделано с ними. Если есть ошибка, то Controller направит вас к error view.

Мои знания основаны на моем одномесячном опыте с Агави. Надеюсь, это поможет.

Ответ 9

  • Просмотр рисует модель и представляет ее пользователю
  • Контроллер обрабатывает ввод пользователя и преобразует его в модификации в модель.
  • Модель содержит логику данных и модификаций

Нет смысла переводить его в код. В любом случае, вы не получите его правильно.

Ответ 10

Просмотр

  • пользовательский интерфейс/ответственный с входным выходом/некоторой валидацией/должен иметь способ уведомлять внешний мир о событиях уровня пользовательского интерфейса

  • знает только о модели

Модель

  • структура данных/представляет данные, которые представлены/не должны содержать бизнес-логику (возможно, только некоторые проверки достоверности данных/структуры)
  • знает только о себе (подумайте о классе Person, который имеет только имя и возраст)

Контроллер

  • отвечает за бизнес-логику/он разбивает представления и склеивает соответствующие модели на них/должен иметь возможность реагировать на просмотр событий/доступ к другим слоям приложения (постоянство/внешние службы/бизнес-уровни и т.д.)

  • знает все (по крайней мере, View и model) и отвечает за склеивание всего вместе