在JavaFX中使用ObservableList是否违反模型 - 视图 - 控制器分离?

brc*_*low 12 java model-view-controller javafx arraylist observablelist

我正在尝试研究JavaFX,因为我想将它用作我程序的GUI.我的问题基本上是一个概念问题:

到目前为止,我的程序主要是MVC模式的"模型"部分; 也就是说,我的几乎所有代码都是类的意义上的抽象的OO表示,所有代码都是逻辑代码.

由于我不想成为我的程序的唯一用户,我想添加MVC的"视图"部分,以便人们可以轻松地使用和操作我的程序的"模型"部分.为此,我想使用JavaFX.

在我的"Model"类中,我显然使用了Java Collections API中的各种Lists,Maps和其他类.为了让我的程序的用户操作这些底层列表和地图,我想在JavaFX中使用Observable(List/Map)接口.

澄清情况的具体例子:

假设我有一个MachineMonitor类,每3分钟检查一次机器的某些属性,例如连接是否仍然良好,齿轮转动的速度等等.如果满足某些不等式(比如说速度)齿轮下降到1转/秒的速度)MachineMonitor触发RestartMachineEvent.

目前我使用ArrayList < MachineMonitor >来跟踪所有单独的MachineMonitor.现在扩展到MVC的"视图"部分,我希望用户能够操作显示MachineMonitor列表的TableView,以便他们可以创建和删除新的MachineMonitor来监视各种机器.

这样我就可以跟踪我的程序用户想要做什么(比如,为机器#5 创建一个MachineMonitor,检查齿轮的转/秒是否低于0.5)我使用ObservableList < MachineMonitor > TableView的基础列表.

链接程序的"模型"和"视图"的最简单方法就是将"模型"类更改为具有ObservableList < MachineMonitor >而不是ArrayList < MachineMonitor >但是(转到问题主题)我觉得这非常混乱,因为它混合了"模型"和"查看"代码.

一种天真的方法是对TableView 使用ObservableList < MachineMonitor >并保留我的ArrayList < MachineMonitor >的使用.但是,根据JavaFX规范,对ObservableList < MachineMonitor >所做的更改不会影响基础List.

鉴于此,是为了解决这一难题,以便为ObservableList一个ChangeListener的最佳方式< MachineMonitor >该"传播"到ObservableList <所做的更改MachineMonitor >到底层"模型"的ArrayList < MachineMonitor >?也许把它放在一个名为MachineMonitorController的类中?

这种临时解决方案看起来非常混乱且非理想.

我的问题是:在这种情况下,保持"模型"和"视图"之间几乎完全分离的最佳方法是什么?

jew*_*sea 11

简而言之,我认为使用ObservableList不会破坏MVC合约.

其余的,你可以阅读或不按你的意愿,因为它非常烦人.

建筑图案背景

Observable在MVC样式体系结构中很有用,因为它们提供了一种通过松散耦合在MVC组件之间来回传递数据的方法,其中模型和视图类不需要直接相互引用,而是可以使用某些共享数据传递数据流的模型.Observable模式和MVC风格的体系结构概念在Xerox PARC中大致同时出现并不是巧合 - 事情是相互关联的.

正如Martin Fowler的GUI架构所述,构建GUI的方法有很多种.MVC只是其中之一,是他们所有人的祖父.很好地理解MVC(经常被误解)并且MVC概念适用于许多地方.为了您的应用程序,你应该使用哪种感觉最适合您的系统,而不是严格遵循规定的图案(除非你正在使用一个特定的框架,强制执行给定的模式),也开放给应用程序中采用不同的模式,而不是试图鞋拔子一切都变成了一个概念框架.

Java Bean是几乎所有Java程序的基础部分.虽然传统上通常只在客户端应用程序中使用,但是观察者模式通常PropertyChangeListenersJava Bean规范创建以来的一部分.JavaFX的可观察和绑定元素是对早期工作的重做,从中学习构建更方便使用和更容易理解的东西.也许,如果JavaFX可观察和绑定元素在十年或十二年前作为JDK的一部分存在,那么这些概念将比一些纯GUI框架更广泛地用于更广泛的库和框架中.

忠告

我建议考虑MVVM模型和其他GUI架构.

如果你想要一个遵循模型,视图,演示者风格的简单框架,肯定会给afterburner.fx一个旋转.

我认为正确的架构选择取决于您的应用程序,您的经验以及您要解决的问题的大小和复杂性.例如,如果您有分布式系统,那么您可以遵循REST原则而不是(或除了)MVC.无论您选择哪种,架构都应该帮助您解决手头的问题(可能还有未来的问题)而不是相反的问题.过度构建解决方案是一个常见的陷阱,并且很容易做到,所以尽量避免使用它.

警告

需要注意的一点需要注意的是,可观测量必然会产生副作用,这种副作用难以推理,并且可能与隔离概念相对立.JavaFX提供了一些很好的工具,例如ReadOnlyObjectWrapperReadOnlyListWrapper,以帮助限制对observables的影响(如果你愿意,可以进行损坏控制),这样它们就不会在你的系统中运行.使用这些工具(和不可变对象)而不顾一切地放弃.

从示例中学习

对于使用observable构建的简单JavaFX应用程序,请参阅tic-tac-toe.

有关使用基于FXML的组件构建大型复杂JavaFX应用程序的好方法,请参阅SceneBuilder和SceneBuilderKit的源代码.源代码在JavaFX mercurial源代码树中可用,只需检查并开始学习.

阅读JavaFX UI控件架构.检查JavaFX控件源代码(例如ButtonButtonSkinListViewListViewSkin),以了解如何使用JavaFX结构应用MVC等概念.基于该学习,尝试使用JavaFX控件框架提供的体系结构创建一些您自己的自定义控件.通常,在构建自己的应用程序时,您不需要创建自己的控件(至少是从JavaFX Control派生的控件).JavaFX Controls体系结构专门用于支持构建可重用控件的库,因此它通常不一定适用于所有目的; 相反,它提供了一种经过验证的方法的具体演示,以完成某些事情.采用和改进经过验证的解决方案有很长的路要走,确保您不会不必要地重新制造东西,并且可以建立坚实的基础,并从其他人的试验中学习.

关于你的具体例子

我建议你一起去:

链接程序的"模型"和"视图"的最简单方法就是将"模型"类更改为具有ObservableList而不是ArrayList

也许使用ReadOnlyListWrapper将ObservableList从MachineMonitor暴露给外部世界,这样任何东西都不能过度地修改它.

设置一些封装视图的其他结构(例如ControlPanel和ControlPanelSkin),并为其提供对只读可观察的MachineMonitor列表的引用.ControlPanelSkin可以封装TableView,图形或您想要用于监视计算机的任何可视旋钮和小部件.

使用这种结构可以有效地将视图与模型隔离开来.该模型根本不了解UI,ControlPanelSkin实现可以更改为完全不同的可视化表示或技术,而根本不需要更改核心MachineMonitor系统.

以上只是概述了一般方法,您需要根据具体示例进行调整.


Jam*_*s_D 10

我不同意ObservableList在你的"模型"类中使用a违反了MVC分离.一个ObservableList纯粹的数据表示; 它是模型的一部分,而不是视图的一部分.我( 其他人)在我的应用程序的所有层中的模型表示中使用JavaFX属性和集合.除此之外,我还指出了如何使用(或者至少)绑定到JSF的JavaFX属性.(我应该提到的是,不是每个人都同意在服务器端使用FX属性的方法;但是我真的没有看到任何方式来使它们成为视图的一部分.)

由于JavaFX现在是Java标准版的完全成熟部分,因此您不会添加任何其他依赖项.(ObservableList不仅是Java SE的一部分,也不是ArrayList的一部分.)

另外,如果你这样做

List<MachineMonitor> myNonObservableList = ... ;

ObservableList<MachineMonitor> myObservableList = FXCollections.observableList(myNonObservableList);
myObservableList.add(new MachineMonitor());
Run Code Online (Sandbox Code Playgroud)

可观察列表由不可观察列表支持,因此也会发生更改myNonObservableList.如果您愿意,可以使用这种方法.