类Javafx的静态实例

时间:2015-06-11 14:42:31

标签: java javafx static

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

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

    public static loggedUserData user  = new loggedUserData();

然后从任何地方访问它:

    demo.user.set(...);

虽然类方法和字段是非静态的。我认为可以有更好的方法来解决这个问题。

1 个答案:

答案 0 :(得分:0)

您的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...
}

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

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