加载FXML的两种方式;为什么一个比另一个更受欢迎?

Two ways to load FXML; why is one preferred over the other?

我正在寻找关于为什么我们应该在加载和显示新的 FXML 阶段时使用一种方法而不是另一种方法的反馈。

大多数时候,我会看到教程等显示从单独的 class 完成的阶段加载。但是,它也可以在 FXML 文件的控制器本身内完成,我个人认为这种方式更简洁、更易于管理。

考虑以下 Main.java class:

public class Main extends Application {

    @Override
    public void start(Stage stage) throws Exception {

        // Method 1:
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout.fxml"));
            loader.setController(new LayoutController());

            stage.setScene(new Scene(loader.load()));
            stage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

这似乎是流行的方法。它创建控制器并设置 Scene 然后显示它。

但是,如果我们将 start() 方法改为:

@Override
public void start(Stage stage) throws Exception {

    LayoutController controller = new LayoutController();
    controller.showStage();

}

并将 FXML 加载代码移动到 LayoutController 构造函数中,结果是相同的:

public class LayoutController {

    @FXML
    private Label label;

    private Stage stage = new Stage();

    public LayoutController() {

        // Method 2:
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout.fxml"));
            loader.setController(this);

            stage.setScene(new Scene(loader.load()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void showStage() {
        this.stage.showAndWait();
    }
}

我在这里看到的好处是视图和逻辑之间的更多分离。 LayoutController 及其关联的 FXML 文件的所有内容都包含在一个地方。

所以我的问题是:第二种方法有什么问题?我假设它不是标准方法是有原因的,但我看不出有任何缺点。

Would a question like this be more suited to Code Review? I'm not really asking for opinions, as there seems to be a general "rule" that the first method be used.

在这种情况下没有太大区别。

对于较大的程序,第二种方法并不理想:

违反了single responsibility principle:

class负责:

  • 创建场景
  • 创建舞台
  • 显示舞台(更糟糕的是,它以可能干扰其他逻辑的方式执行此操作 (showAndWait))
  • 它是视图的控制器,可能会负责处理多个事件

此外,class 的设计方式可以防止责任毫无问题地转移到其他 classes。

在较大的程序中,您可能希望创建一个 class 来管理向视图传递数据、安排 windows 或将视图显示为场景的一部分等。第二种方法不适合这种情况。

此外,不重复自己也更难。除非将逻辑移至通用超类型,否则还需要在每个控制器中实现显示场景的逻辑 class。重复相同或相似的代码会导致代码难以维护。


注意: 使用单个 class 加载 fxml 并用作控制器不一定是坏事,但你应该使用 Introduction to FXML.

中介绍的自定义组件方法