1 回答
TA贡献1934条经验 获得超2个赞
恕我直言,由于以下几个原因,实现非常糟糕:
单例模式没有正确实现
单例模式用于通过static方法访问包含相关数据/功能的实例,但此实例应包含所有相关数据作为实例字段。
rootStage和setUp是static虽然。
您将数据存储在不再需要的字段中
您永远不会从循环中loadedFxml或loadedPanes在循环外读取。您可以改为在循环体中创建局部变量。
一切都立即加载
对于几个小场景,这可能没有太大区别,但是随着您添加越来越多的场景,这将增加启动时间。考虑延迟加载场景。
场景数据保存在不同的数据结构中
不是什么大问题,但它使类更难维护。该enum数据的一部分用于创建存储/接入场景fxmlFiles中包含的另一半。每次添加/删除场景时,您都需要更新代码的两部分。在这种情况下,最好将 url 数据存储在枚举本身中:
public enum States {
MAIN_MENU("../gui/MainWindow.fxml"), NEW_GAME("../gui/NewGameWindow.fxml");
private final url;
States(String url) {
this.url = url;
}
}
for(States state : States.values()) {
FXMLLoader loader = new FXMLLoader(getClass().getResource(state.url));
...
}
请注意..,如果您将程序打包为 jar ,您在此处使用的 url 将停止工作。
但是首先使用 aenum是一个有问题的决定。这样,您将无法在不重新编译的情况下添加/删除场景。
使用static似乎根本没有必要
static如果可能,最好完全避免使用。(请参阅为什么静态变量被认为是邪恶的?)。
如果我假设您只使用SceneManager它加载的场景中的类(并用于显示初始场景)是正确的,那么将SceneManager实例传递给场景的控制器以避免SceneManager.getInstance在这些类中使用并不难(请参阅传递参数 JavaFX FXML ):
控制器的超类
public class BaseController {
protected SceneManager sceneManager;
void setSceneManager(SceneManager sceneManager) { // if SceneManager and BaseController are in different packages, change visibility
this.sceneManager = sceneManager;
}
}
FXMLLoader loader = ...
Pane pane = loader.load();
BaseController controller = loader.getController();
controller.setSceneManager(this);
为简单起见,使用 url 作为场景的标识符,您可以改进实现:
public class SceneManager {
private final Stage rootStage;
public SceneManager(Stage rootStage) {
if (rootStage == null) {
throw new IllegalArgumentException();
}
this.rootStage = rootStage;
}
private final Map<String, Scene> scenes = new HashMap<>();
public void switchScene(String url) {
Scene scene = scenes.computeIfAbsent(url, u -> {
FXMLLoader loader = new FXMLLoader(getClass().getResource(u));
try {
Pane p = loader.load();
BaseController controller = loader.getController();
controller.setSceneManager(this);
return new Scene(p);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
});
rootStage.setScene(scene);
}
}
这使您可以
为不同阶段创建不同的经理
首先在需要时加载场景
动态添加更多场景
防止
switchScene
被调用但阶段是的状态null
简化对
SceneManager
in 控制器类的访问sceneManager.switchScene
SceneManager
在程序完成之前可能可用于垃圾收集,因为没有对它的静态引用。
添加回答
举报