This is a problem I face a lot of times when I am designing a new app. I'll use a sample problem to explain this.
I am writing simple game, so I want to hold a list of players. I have few options...
private static ArrayList<Player> players = new ArrayList<Integer>(); public Player getPlayer(int i){ return players.get(i); }
but this a global state
class PlayerList{ private PlayerList instance; private PlayerList(){...} public PlayerList getInstance() { if(instance==null){ ... } return instance; } }
but this is bad because it's a singleton
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. I didn't actually solve anything.
What is the optimum solution? (currently I use Singleton approach)
Singleton class ensures that not more than one object is created. However, having a global object doesn't ensure this. This class will not create more than one object. This is the purpose of the Singleton class.
For Dependency Injection, typically you would create an instance of the service outside of the target object (the client) and pass it to the client. For a Singleton, the object instantiates itself only once and you can only get/set properties or use methods of the object; you cannot create a new singleton object.
Singletons have global instance variable which points to the singleton. The instance is global. The trouble with global variables is that they are transitive. It is not just the global variable marked with static which is global but any other variable/object which is reachable by traversing the object graph.
Singleton is a design pattern, It means that there will be a single copy of your object inside server memory, which will be shared among all the requests (http/client). So, when you register any dependency in your application as a Singleton, then you will get a single copy of an object per server/node/instance.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With