views:

332

answers:

4

this is a problem i face lot of times when i am designing a new app i'll use a sample problem to explain this

think i am writing simple game.so i want to hold a list of players. i have few options..

1.use a static field in some class

private  static ArrayList<Player> players = new ArrayList<Integer>();  
public Player getPlayer(int i){
    return players.get(i);
}

but this a global state

2.or i can use a singleton

class PlayerList{
    private PlayerList instance;
    private PlayerList(){...}
    public PlayerList getInstance() {
        if(instance==null){
            ...
        }
        return instance;
    } 
 }

but this is bad because it's a singleton

3.Dependency injection

class Game {
    private PlayerList playerList;
    public Game(PlayerList list) {
        this.list = list;
    }
    public PlayerList getPlayerList() {
        return playerList;
    }
}

this seems good but it's not, if any object outside Game need to look at PlayerList (which is the usual case) i have to use one of the above methods to make the Game class available globally. so I just add another layer to the problem. didn't actually solve anything.

what is the optimum solution ? (currently i use Singleton approach)

A: 

Wait, why are Singletons bad? I love the Singleton. But only once.

dustmachine
I'm commenting on the statement in the question "this is bad because it's a singleton." I don't believe that is enough explanation for something to be bad. Doesn't the Spring Framework construct singletons all over the place? Is it not the default when it builds a service?Or are you down-voting me because of the "only once" joke?
dustmachine
I liked this joke the first time only.
HDave
+1  A: 

The idea behind dependency injection is as the name states to inject dependencies. So whatever object needs to know about the player list will be injected with it. Usually, it makes a lot of sense to use dependency injection as extensively as possible before switching to dependency lookup or some other mechanism. This will also make it possible to extend the game later to have different player lists for different levels or whatever extension you might think about.

Johannes Stiehler
k, but what should do when i want to use PlayerList instance in some where else ?
Manu
You would again inject it. A framework such as Spring (provided you program Java) will make this a lot easier for you. Anything that is not a service or singleton itself and thus cannot be reasonibly injected with the PlayersList will be created by some sort of factory which in turn can very well be injected with the PlayersList and can pass it along to the objects it creates.However, if you end up injecting your PlayerList into each and every object you should have some second thoughts about your design especially encapsulation and information hiding.
Johannes Stiehler
+1  A: 

If you need PlayerList outside of Game, maybe Game is the wrong class for this? If any other object needs PlayerList, either they need to have the List injected as well, or maybe you should move the list to this class instead of the Game class.

If you have different lifetimes for Game, PlayerList and other Classes, maybe also consider using a Factory to group them. Check this Google Testing Blog article for details.

FrankS
1)maybe Game is the wrong class for this,but still if i put inside another class, problem is still there.because now i cant use it in Game class.2)passing PlayerList to all the required class doesn't make sense, sine they are made in deffrent Factory class.
Manu
+2  A: 

That's why DI Containers manage lifecycle. Let the Playerlist be a singleton in terms of container lifecycle. Gives you full testability of components and let's the container (not you) get its hands dirty.

flq
+1 - You hit the nail on the head!
TrueWill