Использование ObservableList в JavaFX идет против разделения Model-View-Controller?

Я пытаюсь изучить JavaFX, потому что я хочу использовать его в качестве GUI моей программы. Мой вопрос по существу концептуальный:

на сегодняшний день моя программа в основном является "модельной" частью шаблона MVC; то есть почти весь мой код является OO-представлением абстракций в смысле классов, и весь этот код является логическим кодом.

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

в моих классах" модели " я, очевидно, использую различные списки, карты и другие классы из API коллекций Java. Чтобы позволить пользователям моей программы манипулировать этими базовыми списками и картами, я хочу использовать наблюдаемые интерфейсы(список/карта) в JavaFX.

конкретный пример, чтобы внести ясность в ситуацию:

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

В настоящее время я использую ArrayListMachineMonitor> отслеживать всего индивидуала MachineMonitor. Теперь, расширяясь до части "View" MVC, я хочу, чтобы пользователь мог манипулировать TableView, который отображает список MachineMonitors, чтобы они могли, например, создавать и удалять новые MachineMonitorдля мониторинга различных машин.

чтобы я мог отслеживать, что хочет сделать пользователь моей программы (скажем, создать MachineMonitor для машины #5 которая проверяет для того чтобы увидеть если поворот / sec gears падает ниже 0.5) я использую ObservableListMachineMonitor> в качестве базового списка для TableView.

самым простым способом связать "модель" и "вид" моей программы было бы просто изменить класс "модель", чтобы иметь ObservableListMachineMonitor> а не ArrayListMachineMonitor> но (переходя к теме вопроса) я чувствую, что это очень грязно, потому что он смешивает "модель" и "просмотр" кода.

A наивным подходом было бы использовать ObservableListMachineMonitor> для TableView и сохранить использование моего ArrayListMachineMonitor>. Однако, изменения, внесенные в ObservableListMachineMonitor> не влияют на базовый список согласно спецификациям JavaFX.

учитывая это, лучший способ решить эту головоломку, чтобы сделать ChangeListener для ObservableListMachineMonitor> это "распространяет" изменения сделано в ObservableListMachineMonitor> к базовой" модели " ArrayListMachineMonitor>? Возможно, поместите это в класс MachineMonitorController?

Это специальное решение кажется очень грязным и неидеальным.

мой вопрос: Каков наилучший способ сохранить почти полное разделение между "моделью" и "представлением" в этом сценарии?

2 ответов


Я не согласен с тем, что использование ObservableList в вашем классе" модель " нарушает разделение MVC. Ан ObservableList - это чисто представление данных; это часть модели, а не часть представления. Я (и другие) используйте свойства и коллекции JavaFX в представлениях моделей на всех уровнях моих приложений. Среди прочего, я указываю, как я использую свойства JavaFX, которые (или могут быть, по крайней мере) привязаны к JSF. (Я должен упомянуть, что не все согласен с подходом использования свойств FX на стороне сервера; однако я действительно не вижу никакого способа сделать аргумент, что они каким-то образом являются частью представления.)

поскольку JavaFX теперь является полноценной частью Java standard edition, вы также не добавляете никаких дополнительных зависимостей. (ObservableList является не менее частью Java SE, чем ArrayList.)

кроме того, если вы делаете

List<MachineMonitor> myNonObservableList = ... ;

ObservableList<MachineMonitor> myObservableList = FXCollections.observableList(myNonObservableList);
myObservableList.add(new MachineMonitor());

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


Короче говоря, я не думаю, что использование ObservableList нарушает контракт MVC.

Архитектурный Фон Шаблон

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

Как отметил в архитектуры GUI Мартина Фаулера, существует множество различных подходов к созданию GUIs. MVC-это только один из них, своего рода дедушка из них всех. Приятно хорошо понимать MVC (это часто неправильно понимается) и концепции MVC применимы во многих местах. Для вашего приложения вы должны использовать систему, которая чувствует себя лучше для вас, а не жестко следовать заданному шаблону (если вы не используете определенную структуру, которая обеспечивает данный шаблон), а также быть открытыми для принятия различных шаблонов в приложении, а не пытаться загнать все в единую концептуальную структуру.

Java Beans являются фундаментальной частью почти всех Java программы. Хотя традиционно часто используется только в клиентских приложениях, шаблон Observer, через PropertyChangeListeners, был, по уважительной причине, частью спецификация Java Bean С момента его создания. Наблюдаемые и связывающие элементы JavaFX являются переработкой этой более ранней работы, изучая ее, чтобы построить что-то, что более удобно работать и легче понять. Возможно, если бы JavaFX наблюдаемые и связывающие элементы существовали десять или двенадцать лет назад как часть JDK, такие концепции будут более широко использоваться в более широком спектре библиотек и фреймворков, чем пара чистых фреймворков GUI.

советы

Я предлагаю рассмотреть вопрос о модель MVVM и другие архитектуры GUI.

Если вы хотите мертвую простую структуру, которая следует за моделью, представлением, стилем презентатора, определенно дайте форсаже.fx спина.

Я думаю, правильный выбор архитектуры зависит от вашего приложения, вашего опыта и размера и сложности проблем, которые вы пытаетесь решить. Например, если у вас есть распределенная система, вы можете следовать принципы отдыха вместо (или в дополнение к) MVC. Какой бы вы ни выбрали, архитектура должна помочь вам в решении проблемы в (и возможно будущие проблемы), а не наоборот. Над-architecting решение общая ловушка и очень легко сделать, поэтому попробуйте избегать его.

предостережение

ReadOnlyObjectWrapper и ReadOnlyListWrapper, чтобы помочь ограничить воздействие (контроль повреждений, если хотите) на наблюдаемых, чтобы они не сходили с ума в вашей системе. Используйте такие инструменты (и неизменяемые объекты) С опрометчивой энергией.

учитесь на примерах

для простого приложения JavaFX, которое построено с использованием наблюдаемых, обратитесь к крестики-нолики.

для хорошего способа структурирования большого и сложного приложения JavaFX с компонентами на основе FXML обратитесь к исходному коду для SceneBuilder и SceneBuilderKit. Исходный код доступен в JavaFX mercurial дерево источников, просто проверьте это и начать обучение.

читать на JavaFX UI управляет архитектурой. Проверьте исходный код элементов управления JavaFX (например, и ButtonSkin или ListView и ListViewSkin), чтобы увидеть, как такие понятия, как MVC, могут быть применены с помощью структур JavaFX. На основе этого обучения попробуйте создать некоторые собственные пользовательские элементы управления с помощью архитектуры что JavaFX управления framework обеспечивает. Часто, когда вы создаете свое собственное приложение, вам не нужно создавать свои собственные элементы управления (по крайней мере, те, которые получают форму JavaFX управления). Архитектура элементов управления JavaFX специально разработана для поддержки создания библиотек многоразовых элементов управления, поэтому она не обязательно подходит для всех целей; вместо этого она обеспечивает конкретную демонстрацию одного проверенного способа сделать определенные вещи. Принятие и адаптация доказано решения в значительной степени гарантируют, что вы не будете изобретать вещи без необходимости, и позволяют вам строить на прочной основе и учиться на испытаниях других.

относительно вашего конкретного примера

Я советую вам пойти с:

самый простой способ связать "модель" и "вид" моей программы-просто изменить класс "модель", чтобы иметь ObservableList, а не ArrayList

может использовать ReadOnlyListWrapper, чтобы выставить ObservableList из MachineMonitor во внешний мир, так что ничто не может изменить его излишне.

настройте другую структуру, которая инкапсулирует представление (например, ControlPanel и ControlPanelSkin) и предоставьте ему ссылку на список MachineMonitors только для чтения. ControlPanelSkin может инкапсулировать TableView, график или любые визуальные ручки и виджеты, которые вы хотите использовать для пользователя для мониторинга машины.

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

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