Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to singleton for unique resources

I keep reading over and over again that one should avoid using singletons for various reasons. I'm wondering how to correctly handle a situation where a class represents a unique system resource. For example, a AudioOutput class using SDL. Since SDL_OpenAudio can only be open once at a time it makes no sense having more then one object of this type and it seems to me preventing accidentally making more then one object would actually be good.

Just wondering what experienced programmers think about this, am i missing another option ?

like image 548
Unimportant Avatar asked Dec 09 '22 00:12

Unimportant


1 Answers

One of the problems with Singleton is that most often its usage breaks the Inversion of Control principle (or Dependency Inversion in terms of SOLID).

Singleton doesn't only prevent creating more than one object, it also exposes this object to be accessed from everywhere in your code. This is bad, because if you decide to change the way your object is created/accessed, you would have to change all the places in your code which expect, for example, that they should access it via a static SingletonClass.GetInstance().

Also, when you implement unit testing, it's often needed to use mocks instead of real objects. In your situation, if you wanted some module to be unit-tested, and if that module accessed a real audio output via SingletonClass.GetInstance(), it would become very hard to substitute the real audio output with a stub.

On the other hand, if your module acquired the audio output object via dependency injection (e.g., as a parameter passed to constructor), then while testing, instead of the real audio output object, you could inject a stub which implemented the same interface.

Of course, on the level where you inject such objects, you could use singleton to ensure there's only one instance at a time. The main point is that the underlying code should not care about how many objects there can be or how they are acquired - it just works with what's injected.

So as a bottom line, you can use Singleton if you really think it's needed, but don't allow it to be accessed as global state.

like image 65
Dmytro Shevchenko Avatar answered Dec 24 '22 09:12

Dmytro Shevchenko