Java Constructor Injection

181 views Asked by At

Let's say I have a class resources which instantiates all of my OpenGL / Java game objects and I then pass these via constructor to my Scene class (which requires them), like so (simplified example).....

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);
    }
}

Obviously my Scene's constructor would need to take 4 arguments like so:

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;
    }
}

As more objects are required, the constructor grows ever longer. Now let's say I do something like the following instead:

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;
    }

}

Both options would allow me to use objects within my mainMenuScene like so:

hero.move();

The 2nd seems to be little neater as the constructor will never need to take any additional arguments. However as far as I can recall, I've never really seen any examples like this. Is this a valid technique? Would I run into an problems using it?

2

There are 2 answers

7
Viraj Nalawade On BEST ANSWER

Short Answer:-Yes the technique is valid and it should work fine.
Longer part:-
I would like to suggest two design approaches to consider

The essence pattern

The fluent interface pattern

These are both similar in intent.

Also the builder pattern can be helpful. We see it many times using hibernate. For your class it could like below:-

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}


}

And then you could create objects using chaining something like below:-

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

P.S. Even if you don't want to use above patterns I recommend three changes or habits.
1. Class name start with uppercase alphabet and
2. A convention of organizing the arguments alphabetically.
3. Probably you want to set acces level of the members to private.

2
markspace On

I like it. Instead of Resources, I like to call it an ApplicationContext and use the same way.

I've been critized for creating a "God Object". I disagree with this. As long as the ApplicationContext is thin and only holds objects, but doesn't know anything about them (call any methods), then it's fine. It could be replaced by a List or Map, except I like the additional type checking.

See the Service Locator pattern for another way of doing this.