This may sound like a stupid question, but can DI be used everywhere where a Singleton is needed? Or are there use cases where a Singleton makes more sense? A professor of mine said that there a few but valid cases where a Singleton is "good enough" but I'm somehow not happy with that :-/.
One of the topics in DI is the lifetime of the object which will be injected. Example lifetimes include Singleton as well as Transient, HttpContext, ThreadLocal, Custom etc... So when using DI you could specify an object to be of Singleton lifetime, may be a config class which gets populated at application start. This would seem like a nice class to have as a Singleton.
The Singleton pattern is a powerful one, but like all design patterns they can be more harm than good when used in an incorrect manner. DI and the avoidance of the Singleton also gives rise to better testability.
Cheers for now,
Andrew
Singleton is a pattern. It often shows up in DI containers or as static
APIs. I assume you are referring to the static
flavor.
Objects exposed through static
members provide the lowest-possible friction to consumers; that is why they are so attractive. Dependency Injection addresses the same problem (object access) in a different way. With DI, the lifetime of dependencies is a configuration detail, not an inherent fact.
Here is another answer of mine which addresses this issue:
Wherever possible, I would certainly use dependency injection for singleton objects. Even if you are unlikely to inject anything other than one particular implementation of your object, there is very little downside to using injection, and lots of potential upside. In my experience, dependency injection makes it easier for someone reading the code to understand dependencies, makes code easier to refactor, improves testability, and often improves build times.
That said, I have run into code where I would have ideally liked to use injection, but opted not to. Here are some examples.
- I'm dealing with an API that I can't easily change.
- I'm writing code where the API would seem really strange if I required the client to inject something that they shouldn't be aware of. This is true of some static utility libraries, like functions to parse strings, where I have a helper object that I don't want my users to know about. I'll usually try to avoid this situation though.
- I'm writing experimental code that I'm going to throw away. In this case, I will often take shortcuts to get something working quickly, with the understanding that the code should be deleted or refactored later.
If you haven't used them already, you may want to check out dependency injection frameworks. I've been quite happy using Google Guice in Java code.