【问题标题】:What do we consider the model to be with MVVM (applied to JavaFX)?我们认为模型与 MVVM(应用于 JavaFX)的关系是什么?
【发布时间】:2019-01-14 00:43:29
【问题描述】:

我对如何在 JavaFX 中组织代码有点困惑(假设我打算采用 MVVM 方式)。

考虑下图的标准 4 层架构:

MVVM 中的“模型”位于何处?它是在“用户界面”层内还是在“应用程序/域层”上?我会想象 MVVM 的模型是适合当前视图的后端模型的表示(投影),但我不确定我在网上看到的情况。

举个例子:

我有一个简单的冰淇淋应用程序。它的应用层暴露了方法:

  • IceCreamService.iceCreams(): List<String>;
  • IceCreamService.flavours(iceCream: String): List<String>

UI 将有一个包含冰淇淋列表的组合框,然后根据用户的选择,他可以选择一些口味。然后是提交订单的按钮。

问题是:

我们认为这里的模型是什么?这是IceCreamService 我们所说的模型还是模型是我们在 UI 级别创建的由属性/可观察对象组成的类?如果是后者,谁负责用数据填充这个模型? “控制器”(ViewModel)还是应该足够聪明,可以自己做(也就是说,它有对IceCreamService的引用?)

谢谢!

【问题讨论】:

    标签: oop javafx mvvm


    【解决方案1】:

    MVC 及其派生的设计模式总是存在“10 人会找到 12 种实现方式”的问题,因此我将简要指出一些“流行”的实现方式。

    到目前为止,常见的是您的“用户界面”肯定映射到 MVVM 中的“视图”。然后从这里开始有点值得商榷。

    ViewModel 是大脑

    实现 MVVM 的一种流行方式是“ViewModel”是整个应用程序的大脑。在这种情况下,“Application”映射到“ViewModel”,“Domain”映射到“Model”。 ViewModel 控制(并决定)获取数据的内容和方式,以及它想要向 View 公开的内容和方式。大多数时候“模型”只是一个普通的 POJO 类(例如IceCream 类)。

    对于 JavaFX,您可以让 Model 和 ViewModel 中的所有属性由某种 Property 实现(即实现该接口的东西)表示。如果您没有使用“mvvmFX”之类的 API,那么您的视图很可能会将属性绑定到 ViewModel 中的其他属性。如果您使用的是“mvvmFX”(我没有使用),那么您(很可能)将通过属性名称将 View 属性绑定到 ViewModel(这是 WPF 所做的)。

    在这种方法中,ViewModel 负责获取冰淇淋列表。 IceCreamService 可以被认为是一个单独的Service 层,或者您可以假设它是 ViewModel 的一部分(它本身不是 ViewModel,但它属于 ViewModel)。如果您想更新此列表,则由 ViewModel 决定。

    模型作为域

    另一个实现是让模型进行数据管理,很像 hibernate 在 Spring 中所做的。模型类继续表示数据(或实体等),但它带有自己的持久性逻辑。这意味着如果您更新 Model 对象的值(例如更改 IceCream 实例的风格),Model 会知道它是“脏的”,并将更改推送到存储库。

    MVCVM

    我还读到了另一个approach。简而言之,它类似于第一种方法,但它将IceCreamService 类移动到一个名为“Controller”的全新层中。

    你的例子

    根据您的示例,这是说明如何在 JavaFX 中实现它的示例。

    class IceCreamSelectionView { // The FXML controller class used as MVVM View class
        @FXML ComboBox<String> iceCreams;
        @FXML ComboBox<String> flavors;
    
        private final IceCreamSelectionViewModel vm; // The corresponding ViewModel
    
        @FXML private void initialize() {
            Bindings.bindContent(iceCreams.getItems(), vm.getIceCreams());
            Bindings.bindContent(flavors.getItems(), vm.getFlavors());
            vm.selectedIceCreamProperty().bind(iceCreams.valueProperty());
            vm.selectedFlavorProperty().bind(flavors.valueProperty());
        }
    }
    
    class IceCreamSelectionViewModel {
        /*
         * The properties
         */
    
        public final ObservableList<String> getIceCreams() { return iceCreams; }
        public final ObservableList<String> getFlavors() { return flavors; }
        public final StringProperty selectedIceCreamProperty() { return selectedIceCream; }
        public final StringProperty selectedFlavorProperty() { return selectedFlavor; }
    
        private updateIceCreams() {
            iceCreams.setAll(iceCreamService.getIceCreams());
        }
    }
    
    // There is no Model class because both "iceCream" and "flavor" cannot be further broken down.
    

    【讨论】:

    • 嗨。感谢您的长回答!我提出的问题是:在遵循六边形架构的现代应用程序中(例如),将会发生的情况是层(基础设施/域/应用程序)将是给定的,并且由某个团队来构建一个或多个前端-ends(图表上的“用户界面”,最重要的是(它们可以是桌面用户界面,或 REST API,或网站,或 rabbit-mq API 接口等)。跨度>
    • 我的问题是,从这个角度来看,事情会如何发展? FXML当然是视图的一部分,那么Controller仍然会被认为是视图的一部分,再加上ViewModel会连接到底层?
    • 另一个问题:ViewModel 是否应该完全与 UI 控件无关?这是一个很好的启发式方法吗?
    • @devouredelysium 如果您使用 Spring 使用 RESTful,那将是 MVC 设计。在我看来,所有连接到 Web 服务的客户端都是 MVC 设计中的“视图”。然后,如果您计划使用 JavaFX 作为前端来使用 Web 服务,您可以在那里进行 MVVM 设计。这意味着它是更广泛的 MVC 设计中的 MVVM。就个人而言,我已经尝试过这种方法,但它也有自己的问题。
    • 如果你仍然想要一个 JavaFX MVVM 前端,你可以先看看 mvvmFX 是如何工作的。就个人而言,我曾尝试为 MVVM 进行自定义实现,我会说这是很多工作,也有很多问题。通常是的,FXML+FXML 控制器将成为视图,并且您将拥有可以执行逻辑的单独 ViewModel 类,然后您将拥有代表实体的模型类(例如PersonEmployee 等)。
    猜你喜欢
    • 1970-01-01
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 2018-04-14
    • 2019-05-27
    • 2012-08-23
    相关资源
    最近更新 更多