Java 构造函数注入

Java Constructor Injection

假设我有一个 class resources 实例化我所有的 OpenGL / Java 游戏对象,然后我通过构造函数将它们传递给我的场景 class (这需要它们),就像这样(简化示例)......

public class Resources {

    Hero hero;
    Enemy enemy;
    MenuButtons mainMenuButtons;
    Background background;
    Scene mainMenu;

    public void createObjects(){

        hero = new Hero();
        enemy = new Enemy();
        mainMenuButtons = new MenuButtons();
        background = new Background();
        mainMenu = new Scene(hero, enemy, mainMenuButtons, background);
    }
}

显然我场景的构造函数需要像这样接受 4​​ 个参数:

public class MainMenu implements Scene {

    hero Hero;
    enemy Enemy;
    mainMenuButtons MenuButtons;
    background Background;

    public MainMenu(Hero hero, Enemy enemy, MainMenuButtons mainMenuButtons, Background background){

        this.hero = hero;
        this.enemy = enemy;
        this.mainMenuButtons = mainMenuButtons;
        this.background = background;
    }
}

随着需要更多的对象,构造函数变得越来越长。现在假设我改为执行以下操作:

public class MainMenu implements Scene {

    Resources resources;

    public MainMenu(Resources resources){

        this.hero = resources.hero;
        this.enemy = resources.enemy;
        this.mainMenuButtons = resources.mainMenuButtons;
        this.background = resources.background;
    }

}

这两个选项都允许我在 mainMenuScene 中使用对象,如下所示:

hero.move();

第二个似乎更简洁一些,因为构造函数永远不需要接受任何额外的参数。 但是据我所知,我从未真正见过这样的例子。这是一种有效的技术吗?我 运行 使用它会遇到问题吗?

简短回答:-是的,该技术是有效的,应该可以正常工作。
较长的部分:-
我想建议两种设计方法来考虑

essence 模式

fluent界面模式

它们的意图相似。

构建器模式也很有用。我们多次看到它使用休眠。对于您的 class 它可能如下所示:-

public class mainMenu implements Scene {

    private Hero hero;
    private Enemy enemy;
    private MenuButtons mainMenuButtons;
    private Background background;

    public mainMenu setHero(Hero hero){this.hero = hero; return this}
    public mainMenu setEnemy(Enemy enemy){this.enemy = enemy; return this}
    public mainMenu setMainMenuButtons(MenuButtons mainMenuButtons){this.mainMenuButtons = mainMenuButtons; return this}
    public mainMenu setBackground(Background background){this.background = background; return this}


}

然后您可以使用如下链接创建对象:-

mainMenu main =new mainMenu().
setHero(new Hero()).
setEnemy(new Enemy()).
setMainMenuButtons(new MainMenuButtons()).
setBackground(new Background());

P.S。即使您不想使用上述模式,我也建议您进行三个改变或养成习惯。
1. Class 名称以大写字母开头并且
2. 按字母顺序组织参数的约定。
3. 可能您想将成员的访问级别设置为私有。

我喜欢。我喜欢将其称为 ApplicationContext 而不是 Resources 并使用相同的方式。

我因创建 "God Object" 而受到批评。我不同意这一点。只要 ApplicationContext 很薄并且只包含对象,但对它们一无所知(调用任何方法),就可以了。它可以用 List 或 Map 代替,但我喜欢额外的类型检查。

请参阅 Service Locator 模式以了解另一种执行此操作的方法。