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
在程序完成之前可能可用于垃圾收集,因為沒有對它的靜態引用。
添加回答
舉報