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

JavaFX - Наблюдаемые коллекции в классах моделей данных

Ниже приведен простой фрагмент кода JavaFX, чтобы проиллюстрировать мой вопрос.

List list1 = new ArrayList();
list1.add("foo");
...

someListView = new ListView<>();
ObservableList someObservableList = FXCollections.observableList(list1);
someListView.setItems(someObservableList);
...

someObservableList.add("bar");

Если я правильно понял, после вызова метода setItems не только содержимое списка будет отображаться в компоненте ListView Gui, но также после добавления элементов в экземпляр ObservableList, ListView будет автоматически обновляться и автоматически отображать вновь добавленные элементы без необходимости вызова каких-либо дополнительных методов add или refresh.

До сих пор так хорошо. Но что, если я добавлю что-то в исходный список (т.е. list1). Эти изменения не распространяются автоматически. Это имеет смысл, но иногда это неудобно.

Конечно, в классическом Java-приложении модель приложения не состоит из экземпляра ObservableCollection. Поэтому всякий раз, когда вы добавляете что-то в модель, вам всегда придется обновлять экземпляры ObservableLists, которые были получены из исходного списка. Видимо, это неизбежно, верно?

Это заставило меня задуматься: разумно ли модифицировать типы типов Collection (например, List, Collection, Set, Iterable,...) в классах модели и заменить их на их альтернативы ObservableCollection с этого момента?

До сих пор я всегда полагал, что эти классы ObservableCollection должны были использоваться только в слое Gui приложения, но, кажется, довольно удобно использовать их везде.

4b9b3361

Ответ 1

Вы можете взломать генератор данных Granite Data Services (написанный в groovy GSP и Java) для создания "связанных" java-классов из ваших классов домена, создавая свойства javafx для хранения данных для основных полей, включая коллекции.

Для этого есть отличный пример: https://github.com/graniteds/shop-admin-javafx, который построен с помощью maven с включенным генератором. Это относится к принципу DRY (Do not Repeat Yourself), и иногда кажется более полезным, что классы домена становятся связующими. Вы изменили свои классы, чтобы иметь свойства javafx: вы сделали что-то похожее на Granite и да, у него есть некоторые преимущества, поскольку он удаляет шаблонный код (аналогично этому: EJB3, похоже, удаляет DTO, сущности - классы домена). Но ваши классы домена тесно связаны с вашими представлениями: он похож на шаблон MVC.

Другим решением является использование библиотеки JFXtras, которая имеет интересный API для генерации на лету слушателей в коллекциях java, чтобы создать свойство javafx. Вот ссылка, где описано: http://ugate.wordpress.com/2012/07/30/javafx-programmatic-pojo-expression-bindings-part-iii/

С помощью JFXtras вы можете использовать свойства только тогда, когда захотите, с относительно простым API (для коллекций это может стать трудным для чтения IMHO), и таким образом вы не модифицируете классы домена, которые не будут стать View related. Но для передовых привязок к коллекциям: это, похоже, не лучшее решение. Это похоже на компромисс между MVC и MVP.

Последнее решение, которое я вижу, состоит в том, чтобы придерживаться шаблона MVP, вы на самом деле его используете, который изначально не позволяет доступ к классам моделей через представление, введя слой Presenter для ссылки на два: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter

Вам нужно будет инициировать и синхронизировать значения вручную между вашими свойствами javafx и вашими классами домена: иногда это то, что вы хотите, и единственный способ достичь этого (например: таким образом вы можете "вернуть" значение старого домена в форма довольно легко, если бы она была привязана, вы потеряли бы последнее "правильное" значение домена). Обратите внимание, что вы можете поместить свои свойства javafx в одноэлементы (используя инфраструктуру IOC, например Spring) для доступа и привязки через разные представления: я вижу их как часть презентатора.

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

Ответ 2

Вообще говоря, я бы избегал любых зависимостей GUI-библиотеки в моем уровне модели. Это ограничит возможное повторное использование. Это справедливо для зависимостей javafx, а также от объектов AWT, таких как Point/Rectangle, которые часто используются (ошибочно) в классах моделей.

Причина проста: ваш код ограничится платформами и фреймворками, Android, например, не поддерживает ни один из упомянутых java-пользовательских интерфейсов, таких как awt. Кроме того, у ORM могут возникнуть проблемы с такими типами, для которых потребуются настраиваемые адаптеры для ваших объектов домена.

Я обнаружил, что использование слегка измененной версии шаблона