gpt4 book ai didi

java - 除了依赖注入(inject)或观察者之外,Java 中单例模式的替代方案

转载 作者:行者123 更新时间:2023-12-02 03:22:19 25 4
gpt4 key购买 nike

我正在制作一个 JavaFX 应用程序,它有四个根 Controller 。其中每一个都控制选项卡上的 View 。选项卡选择器没有 Controller ,因为它除了选择要显示的四个 View 中的哪一个之外没有其他功能。这些 Controller 需要有权访问相同的数据,并且它们都可以修改这些数据。

我认为以可读的方式实现此目的的唯一方法是使用静态单例,它存储可由所有四个 Controller 访问和修改的状态。由于显而易见的原因,这并不理想。

我无法使用依赖注入(inject),因为所有 Controller 都是在应用程序启动时初始化的,它们不是由彼此创建的。出于同样的原因,我也不能使用观察者模式。他们无法获得彼此的引用,因此无法观察对方。据我所知,Java 中没有广播通知系统,这很烦人,因为它是一个解决方案。是否有另一种我可以使用的模式,或者可以通过某种方式使其中一种模式发挥作用?

选项卡的 fxml 文件作为选项卡 Pane 中的内容加载。这样做是为了让我可以为每个选项卡使用不同的 Controller 。然后,start 方法加载选项卡 Pane fxml。

<TabPane prefHeight="200.0" prefWidth="200.0"   tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
<tabs>
<Tab text="Data &amp; Statistics">
<content>
<fx:include fx:id="dataViewTabControl" source="DataViewTabControl.fxml" />
</content>
</Tab>
. . .

最佳答案

您可以通过在 FXMLLoader 上设置 Controller 工厂来有效地使用依赖项注入(inject)。 。这允许您控制如何为指定 Controller 类的 FXML 文件创建 Controller 实例 fx:controller属性。 Controller 工厂用于包含的 FXML 文件以及主 FXML 文件。

因此,您可以创建具有应用程序状态的模型类,从 Controller 观察和修改该状态,并创建在所有 Controller 之间共享的单个实例。

定义您的模型:

public class Model { /* ... */ }

因此,如果您使用 Controller 定义 DataViewTabControl.fxml 文件,例如:

<?xml version="1.0" encoding="UTF-8"?>

<!-- imports etc -->

<SomeRootPane fx:controller="com.example.DataViewTabController">

<!-- ... -->

</SomeRootPane>

并定义您的DataViewTabController采取Model构造函数中的参数:

public class DataViewTabController {

private final Model model ;

public DataViewTabController(Model model) {
this.model = model ;
}

}

现在,当您加载主 FXML 文件以及可能具有将模型作为构造函数参数的 Controller 或 <fx:include> 的任何其他文件时做同样的事情,使用调用正确构造函数的 Controller 工厂:

Model model = new Model();

FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml/file"));

loader.setControllerFactory((Class<?> controllerType) -> {
try {
for (Constructor<?> con : controllerType.getConstructors()) {
if (con.getParameterCount() == 1 && con.getParameterTypes()[0]==Model.class) {
return con.newInstance(model);
}
}
// no suitable constructor found: just return default instance
return controllerType.newInstance();
} catch (Exception e) {
System.err.println("Warning: could not load controller");
e.printStackTrace(System.err);
return null ;
}
});

现在您的所有 Controller 都可以访问相同的 Model实例,因此您可以使用通常的 MVC/Observer 模式来更改数据并响应数据的更改。如果您的模型类使用JavaFX property API,这会特别容易。 .

关于java - 除了依赖注入(inject)或观察者之外,Java 中单例模式的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39445001/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com