Esta es la solución más acertada que encomtrarás dar, pero estúdiala detenidamente y valora si se puede adaptar a tu trabajo.
Solución:
No estoy de acuerdo con que el uso de un ObservableList
en su clase “modelo” viola la separación MVC. Un ObservableList
es puramente representación de datos; es parte del modelo y no de la vista. Yo (y otros) utilizamos propiedades y colecciones JavaFX en representaciones de modelos en todos los niveles de mis aplicaciones. Entre otras cosas allí, señalo cómo uso las propiedades de JavaFX que están (o pueden estar, al menos) vinculadas a JSF. (Debo mencionar que no todos están de acuerdo con el enfoque de usar propiedades FX en el lado del servidor; sin embargo, realmente no veo ninguna forma de argumentar que de alguna manera son parte de la vista).
Además, si lo haces
List myNonObservableList = ... ;
ObservableList myObservableList = FXCollections.observableList(myNonObservableList);
myObservableList.add(new MachineMonitor());
la lista observable está respaldada por la lista no observable, por lo que el cambio ocurre en myNonObservableList
también. Entonces puede usar este enfoque si lo prefiere.
Brevemente, no creo que el uso de ObservableList rompa el contrato MVC.
El resto, puede leerlo o no como desee, ya que es bastante largo.
Fondo de patrón arquitectónico
Los observables son útiles en las arquitecturas de estilo MVC porque proporcionan una forma de alimentar datos entre los componentes MVC a través de acoplamientos sueltos donde el modelo y las clases de vista no necesitan referirse directamente entre sí, sino que pueden trabajar con algunos datos compartidos. modelo que comunica el flujo de datos. No es una coincidencia que el patrón Observable y el concepto de arquitectura de estilo MVC se hayan originado aproximadamente al mismo tiempo en Xerox PARC: las cosas están vinculadas.
Como se señaló en las arquitecturas GUI de Martin Fowler, existen numerosos enfoques diferentes para crear GUI. MVC es solo uno de ellos, una especie de abuelo de todos ellos. Es bueno entender bien MVC (a menudo se malinterpreta) y los conceptos de MVC son aplicables en muchos lugares. Para su aplicación, debe usar el sistema que se sienta mejor para usted en lugar de seguir rígidamente un patrón dado (a menos que esté usando un marco en particular que refuerce un patrón dado) y también estar abierto a adoptar diferentes patrones dentro de una aplicación en lugar de tratar de calzar todo en un solo marco conceptual.
Los Java Beans son una parte fundamental de casi todos los programas Java. Aunque tradicionalmente a menudo solo se usa en aplicaciones cliente, el patrón de observador, a través de PropertyChangeListeners
, ha sido, por una buena razón, parte de la especificación Java Bean desde su creación. Los elementos observables y vinculantes de JavaFX son una reelaboración de ese trabajo anterior, aprendiendo de él para construir algo que sea más conveniente para trabajar y más fácil de entender. Quizás, si los elementos observables y vinculantes de JavaFX hubieran existido hace diez o doce años como parte del JDK, tales conceptos se usarían de manera más general en una variedad más amplia de bibliotecas y marcos que un par de marcos GUI puros.
Consejo
Sugiero considerar el modelo MVVM y otras arquitecturas GUI.
Si quieres un marco muy fácil que siga un modelo, vista, estilo de presentador, definitivamente dale una vuelta a afterburner.fx.
Creo que la elección correcta de la arquitectura depende de su aplicación, su experiencia y el tamaño y la complejidad de los problemas que está tratando de resolver. Por ejemplo, si tiene un sistema distribuido, puede seguir los principios REST en lugar de (o además) MVC. Cualquiera que elija, la arquitectura debe ayudarlo a resolver el problema en cuestión (y posiblemente problemas futuros) y no a la inversa. Sobrearquitectura de una solución es una trampa común y muy fácil de hacer, así que trate de evitarlo.
Advertencia
Una advertencia a considerar es que los observables funcionan necesariamente a través de efectos secundarios que pueden ser difíciles de razonar y pueden ser contrarios al concepto de aislamiento. JavaFX presenta algunas buenas herramientas, como ReadOnlyObjectWrapper y ReadOnlyListWrapper, para ayudar a limitar el impacto (control de daños si lo desea) en los observables para que no se vuelvan locos en su sistema. Utilice estas herramientas (y objetos inmutables) con un abandono imprudente.
Aprenda de los ejemplos
Para una aplicación JavaFX simple que se crea utilizando observables, consulte tic-tac-toe.
Para conocer una buena forma de estructurar una aplicación JavaFX grande y compleja con componentes basados en FXML, consulte el código fuente de SceneBuilder y SceneBuilderKit. El código fuente está disponible en el árbol de fuentes mercurial de JavaFX, solo compruébalo y comienza a aprender.
Lea sobre la arquitectura de controles de la interfaz de usuario de JavaFX. Examine el código fuente de los controles JavaFX (por ejemplo, Button y ButtonSkin o ListView y ListViewSkin) para ver cómo se pueden aplicar conceptos como MVC utilizando estructuras JavaFX. Con base en ese aprendizaje, intente crear algunos de sus propios controles personalizados utilizando la arquitectura que proporciona el marco de controles de JavaFX. A menudo, cuando está construyendo su propia aplicación, no necesita crear sus propios controles (al menos los que derivan de JavaFX Control). La arquitectura de controles JavaFX está especialmente diseñada para admitir la creación de bibliotecas de controles reutilizables, por lo que no es necesariamente adecuada para todos los propósitos; en cambio, proporciona una demostración concreta de una forma probada de hacer ciertas cosas. Adoptar y adaptar soluciones comprobadas contribuye en gran medida a garantizar que no reinvente cosas innecesariamente y le permite construir sobre una base sólida y aprender de las pruebas de los demás.
Respecto a su ejemplo concreto
Te aconsejo que vayas con:
La forma más fácil de vincular el “Modelo” y la “Vista” de mi programa sería simplemente cambiar la clase “Modelo” para tener una ObservableList y no una ArrayList
Tal vez use un ReadOnlyListWrapper para exponer ObservableList del MachineMonitor al mundo exterior, de modo que nada pueda modificarlo indebidamente.
Configure alguna otra estructura que encapsule la vista (por ejemplo, ControlPanel y ControlPanelSkin) y proporcione una referencia a la lista de solo lectura observable de MachineMonitors. ControlPanelSkin puede encapsular un TableView, un gráfico o cualquier control visual y widgets que desee utilizar para que el usuario controle las máquinas.
El uso de dicha estructura aísla efectivamente su vista del modelo. El modelo realmente no sabe nada sobre la interfaz de usuario y la implementación de ControlPanelSkin podría cambiarse a una representación visual o tecnología completamente diferente sin cambiar el sistema principal de MachineMonitor en absoluto.
Lo anterior solo describe un enfoque general, deberá modificarlo para su ejemplo específico.