繁体   English   中英

类Javafx的静态实例

[英]Static instances of class Javafx

我有一个包含main方法和start方法的主类。 现在我还有很多其他的课程。 例如,我有一个登录类,注册类,等等。 我有一个仅处理当前登录用户的数据的类。 需要从许多控制器访问该类。 因为这个用户永远只会是一个实例。 我想知道什么是最好的方法,以便每个班级都可以访问它以更新它。

我目前正在应用的是在我的主类中创建一个记录用户数据类型类的静态实例。 然后访问它们。

    public static loggedUserData user  = new loggedUserData();

然后从任何地方访问它:

    demo.user.set(...);

而类的方法和字段不是静态的。 我认为可能有更好的方法来解决此问题。

您的user对象是构成MVC / MVP等设计模型的一部分的应用程序数据:

package application;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;

public class DataModel {
    private ObjectProperty<User> currentUser = new SimpleObjectProperty<>();

    public final ObjectProperty<User> currentUserProperty() {
        return this.currentUser;
    }

    public final User getCurrentUser() {
        return this.currentUserProperty().get();
    }

    public final void setCurrentUser(final User currentUser) {
        this.currentUserProperty().set(currentUser);
    }



    // other properties, etc...
}

在相对简单的应用程序中,我创建了一个单例控制器工厂 ,该工厂引用一个模型实例并将其传递给任何可以接受它的控制器构造函数:

package application;

import java.lang.reflect.Constructor;

import javafx.util.Callback;

public enum ControllerFactory implements Callback<Class<?>, Object> {

    INSTANCE ;

    private final DataModel model = new DataModel();

    @Override
    public Object call(Class<?> type) {
        try {
            for (Constructor<?> constructor : type.getConstructors()) {
                if (constructor.getParameterCount() == 1
                        && DataModel.class.isAssignableFrom(constructor.getParameterTypes()[0])) {
                    return constructor.newInstance(model);
                }
            }
            return type.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

(另一种选择,不是在这里使用单例模式,而是拥有一个接受DataModel的构造函数,并始终将引用传递给同一DataModel实例,这一点通常很自然。)

然后,您可以拥有看起来像

package application;

import javafx.fxml.FXML;
import javafx.scene.control.TextField;

public class LoginController {

    private final DataModel model ;

    @FXML
    private TextField userNameTextField ;

    public LoginController(DataModel model) {
        this.model = model ;
    }

    @FXML
    private void login() {
        model.setCurrentUser(new User(userNameTextField.getText()));
    }

}

package application;

import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class SomeOtherController {

    private final DataModel model ;

    @FXML
    private Label userLabel ;

    public SomeOtherController(DataModel model) {
        this.model = model ;
    }

    public void initialize() {

        // Use EasyBind https://github.com/TomasMikula/EasyBind for
        // more robust binding to a "property of a property"

        userLabel.textProperty().bind(Bindings.select(model.currentUserProperty(), "userName"));
    }
}

如果使用以下惯用法加载FXML文件,则控制器将自动使用(共享)数据模型填充控制器:

package application;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) throws IOException {
        String resource = "Login.fxml" ;
        FXMLLoader loader = new FXMLLoader(getClass().getResource(resource));
        loader.setControllerFactory(ControllerFactory.INSTANCE);
        Parent root = loader.load();
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

对于更复杂的应用程序(或者简单地,如果您更喜欢基于约定/有针对性的方法),请考虑使用专用的JavaFX依赖项注入框架,例如Afterburner.fx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM