Правильная реализация шаблона MVC в разработке GUI с использованием Swing в Java
Во-первых, я пришел из большого фона PHP с MVC, когда я начинал с PHP, я много раз просматривал, чтобы попробовать и улучшить мой MVC-подобный дизайн в PHP. Многим нравится отвечать с ответами, которые мне очень помогли.
Но после начала разработки графического интерфейса в Swing ответы о MVC в Swing совершенно другие. Например, модель также является представлением? Согласно предложениям Oracle TextElementModel
здесь нет никакого логического бизнеса, все, что он делает, это разметка (установка цвета и т. д.) и настройка данных, таких как заданный текст и так далее. Когда я разрабатывал в PHP, не было такого понятия, как AbstractModel
потому что мне всегда говорили, что модель - это не класс или более, это целый слой, который обрабатывает логический бизнес.
В PHP я использовал Services, Data Mappers и Domain Objects, предложенные из этого удивительного ответа, который мне очень помог в PHP: как должна быть структурирована модель в MVC?
Моя попытка
Прочитав еще раз, я решил попробовать и сделать то же самое в Java:
у меня есть ControllerContainer
который создает все контроллеры:
public class ControllerContainer {
private JFrame frame;
public ControllerContainer(JFrame rune) {
this.frame = frame;
}
public void initControllers() {
Atest test = new Atest(frame);
test.registerView("test", new ViewTest(test));
}
}
Как видите, я добавляю представление с именем "test" с экземпляром ViewTest
для контроллера, теперь он будет виден в кадре и может принимать входные данные.
мой Controller
класс, который должен быть абстрактным, но я еще не сделал его абстрактным:
public class Controller {
private JFrame frame;
private Map<String, Component> views = new HashMap<String, Component>();
public Controller(JFrame frame) {
this.frame = frame;
}
protected void registerView(String title, Component c) {
this.views.put(title, c);
this.frame.add(c);
}
protected void deregisterView(String title) {
this.frame.remove(this.views.get(title));
this.views.remove(title);
}
protected Component getView(String title) {
return this.views.get(title);
}
}
И тестовый контроллер:
public class Atest extends Controller {
public Atest(JFrame frame) {
super(frame);
}
public void hit() {
((ViewTest) super.getView("test")).changeColorBlue();
}
}
И мой TestView
:
public class ViewTest extends JPanel {
private final Atest controller;
public ViewTest(Atest c) {
this.controller = c;
setBackground(Color.RED);
setLocation(0,0);
setSize(300, 300);
setLayout(null);
JButton b = new JButton("hello");
b.setSize(150, 150);
b.setLocation(0,0);
b.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent arg0) {
controller.hit();
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
@Override
public void mousePressed(MouseEvent arg0) {
}
@Override
public void mouseReleased(MouseEvent arg0) {
}
});
add(b);
}
public void changeColorBlue() {
setBackground(Color.BLUE);
}
}
Эта проблема
Как вы видите, мое представление создает новую кнопку и добавляет к ней прослушиватель мыши. слушатель будет иметь доступ к контроллеру для передачи ввода. Контроллер получает ввод и меняет представление.
По сути, контроллер мгновенно вынужден обновить представление, без каких-либо серьезных логических действий, поскольку в моем случае это не требуется.
По ссылке, которую я разместил выше, на которую ответил tereško, как я могу правильно использовать его идеи и предложения с Java Swing?
Я действительно смущен, после фона PHP.
Может я недопонимаю и все должно быть по-разному на разных языках? Но я думал, что шаблоны всегда должны быть реализованы одинаково.
Если вам нужна дополнительная информация, дайте мне знать.
2 ответа
Может быть, я неправильно понимаю, и все должно быть сделано по-разному на разных языках?
Там нет недопонимания; шаблон просто применяется по-другому.
Как отмечено в комментарии @ordous и в этом ответе @udalmik, приложение Swing может иметь несколько реализаций шаблона MVC. Как отмечалось здесь и здесь, "не каждое взаимодействие должно проходить через контроллер вашего приложения". Напротив, веб-приложение вполне может "иметь отношение 1:1 между представлениями и контроллерами".
Цитируемая здесь архитектура разделяемой модели Swing "объединяет части представления и контроллера каждого компонента в единый объект пользовательского интерфейса". Контроллеры Swing разбросаны среди потомков JComponent
обычно в делегате пользовательского интерфейса компонента. В качестве конкретного примера BasicButtonUI
содержит BasicButtonListener
это обрабатывает взаимодействие с мышью пользователя.
Почти использовал ответ в ссылке, но тот факт, что его контроллер расширяет
JPanel
разрушил его, полностью смутил меня там.
Это может сбивать с толку, так как простая программа на Swing может вообще не иметь явного контроллера. Как предлагается в этом наброске, контроллер имеет прямой доступ к любому соответствующему виду и модели; он также может прослушивать взаимодействие пользователя с представлением. Этот пример был призван проиллюстрировать простейшее такое взаимодействие. Это просто совпадение, что эффект вызван взаимодействием пользователя с компонентом представления. Например, приведенное здесь моделирование имеет ControlPanel
компонентов представления, которые обновляют представление и модель приложения. DisplayPanel
слушает напрямую ComponentEvent
это требует обновления модели. И т.п.
Тогда контроллер вашего приложения может сосредоточиться на потребностях приложения.
@ Marco13 подробно описывает это и приводит дополнительные примеры в этом ответе.
ШаблонMVC - это обычная парадигма, поэтому между языками прагматики вообще нет различий. Однако реализация и некоторые термины иногда выглядят по-разному. В Java Swing часто можно увидеть два следующих подхода:
1. Классический MVC
Контроллер - прослушивает действия пользовательского интерфейса, выполняет соответствующие обновления модели. Можно слушать действия из разных представлений.
Модель - представляет состояние и логику домена, методы для изменения состояния. Уведомляет слушателей об обновлениях модели (несколько просмотров могут прослушивать обновления). Модель независима и ничего не знает о слушателях и их логике.
Вид - отвечает за пользовательский интерфейс, расположение элементов пользовательского интерфейса, а также прослушивает обновления модели и, при необходимости, обновляет графический интерфейс. Имеет некоторые знания о модели, в примере, показанном ниже, он знает, как обрабатывать список "элементов".
Дизайн простого приложения "To Do" может выглядеть так:
2. MVP (модель представления презентации)
Контроллер действует как посредник между представлением и моделью. Вид становится очень тонким и ничего не знает о модели и взаимодействует только с контроллером. Контроллер прослушивает как View, так и Model и выполняет соответствующие действия.
СамSwing добавляет некоторую путаницу, потому что он использует шаблон MVC для своих компонентов пользовательского интерфейса. Каждый элемент управления UI имеет модель и представление. Это облегчает проектирование новых компонентов пользовательского интерфейса, однако, в "общей картине" всего дизайна приложения - элементы управления пользовательского интерфейса остаются на уровне просмотра.