5

I read So Singletons are bad, then what? which was a great explanation of dependency injection as the solution for inversion of control. The asker assumed singleton and single instance were synonyms, and as others pointed out singleton is a more restrictive example of single instance.

My question is, why did the responder go from single instance to talking about dependency injection? He states:

A cache does not need to be a singleton. It may need to be a single instance if you want to avoid fetching the same data for multiple cache instances; but that does not mean you actually have to expose everything to everyone.

With DI, you have one interface, in this case "Cache". However, you have multiple instances. Instances of VideoPage + instances of MyAccountPage + etc. VideoPage implements IMediaCache which extends Cache. The DI is that the dependent class that makes use of this caching abstraction does so by using the Cache interface as a type in a parameter list (parameter list of constructor if using constructor injection, etc.)

So there are multiple instances (x VideoPages, y MyAccountPages, etc.) The Cache is the "single" thing in this design pattern, but it's not an instance since you can't instantiate an interface.

"Single instance" and "Dependency Injection" to me are separate ideas, so that response confused me.

I also don't know why people saying dependency injection is an alternative to singletons. A singleton forces one instance even if I try to instantiate again. As for dependency injection, again, what is my "single instance"? The Cache isn't, as I explained earlier. And there are multiple instances of classes ultimately implementing the Cache interface.

2 Answers 2

4

Because dependency injection container can and is used for lifetime management. Basically, singleton's main purpose is to maintain lifetime of exactly one instance : it is created once at startup (or first use) and is destroyed when application ends. But if you put both lifetime management and behavior itself in single class (eg. singleton), you break single responsibility principle.

On the other hand, if you have a single top container and use it to manage lifetime of that one instance, based on interface. You can tell you DI container to handle that one implementation of interface as a singleton. So it returns same instance every time it is requested. There are also different lifetimes : per-thread, per-(web)request, etc..

If you use DI instead of static field, then design around this single instance becomes much cleaner. It will also make it easier to change your mind later on, if you realize that what you first thought was a singleton actually isn't.

2
  • 1
    Your description sounds like tomato, tomahto to me. Commented Dec 13, 2014 at 7:18
  • When you said that there are different lifetimes (per-thread, per-(web)request, etc., it just clicked for me
    – IvanD
    Commented Sep 26, 2021 at 3:19
2

My question is, why did the responder go from single instance to talking about dependency injection?

Because Dependency Injection (DI) is one way to ensure that a class has only a single instance. Using the singleton design pattern is another.

If you configure your DI setup to return the same instance whenever someone asks for one, the instance essentially becomes a singleton.

I also don't know why people saying dependency injection is an alternative to singletons. A singleton forces one instance even if I try to instantiate again. As for dependency injection, again, what is my "single instance"?

When you are using DI you should not create instances yourself. Instead you rely on the DI framework to provide them for you.

This means you ask the DI framework to give you a cache. If the DI framework returns the same instance each time, the cache is "a singleton" even though the class that implements the cache does not use the singleton design pattern.

Since "singleton" is potentially confusing it is better to say your cache is a "single instance" unless the context is clear.

With DI, you have one interface, in this case "Cache". However, you have multiple instances. ...

I think you misunderstood the example. VideoPage does not implement the IMediaCache interface. It depends on a class that implements the IMediaCache interface.

The classes implementing IMediaCache could be something like MediaMemoryCache or a MediaDiskCache.

VideoPage depends on an interface rather than a concrete implementation because it should not have to care how data is cached, just that it is.

Whenever the user opens the video page the DI framework injects a cache into the page.

If the DI framework injects the same instance each time then the cache is essentially a singleton because it behaves like a singleton without actually being one. This is the single instance the responder is talking about.

Since you are using an interface you can change the concrete implementation without having to change VideoPage. All you have to do is reconfigure DI to inject SuperVideoCache rather than MediaDiskCache.

Compare that to an actual "singleton" implementation:

You would have to change all classes currently using MediaDiskCache.getInstance() to use SuperVideoCache.getInstance() to change the cache implementation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.