Singletons

Autoinitializing singleton
Manually initialized singleton
Dependency Injection

There have been many discussions about using or avoiding the singleton design pattern. I don't want to go into this (heated) discussion; instead let's compare an approach with a singleton and then at the alternative without using a singleton.

Auto-initializing singleton

First we'll look at the "auto initializing" singleton, This type of singleton auto-creates a new instance when "::Instance()" is called, when no instance is available. Example C++ sourcecode:
Besides having no real control over initialization, it has a really nasty side-effect. When shutting down your Application, order is very important. Especially with bigger software with multiple developers, you easily get into shutdown order issues, unintentionally reinitializing your singleton. I've witnessed this in two projects. In one case there was a thread running feeding a singleton manager with data. The singleton was shutdown, the thread however was still running, so it reinitialized the manager feeding it with data causing thousands of memory leaks. In the other case, a user went back to the mainmenu of the game, and wanted to continue/load a new savegame. Part of the system was shutdown and would be reinitialized depending on the user actions...

Manually Initialized singleton

Look at the (simplified) C++ sourcecode below for a manually initialized singleton (in which you have full control over initialization order).
The code above shows that it's really easy to make a mistake with initialization ordering. In general, I suggest to stay away from the auto-initializing singleton.
So what about the manually initialized singleton? Let's view an example in C++
note: google 'scott bilas singleton' for an example singleton-template implementation. In our example it would have to be extended with a function InstancePointer().

So we have an Application object, which initializes two singletons. The application object has a message loop which is called periodically. In the loop it calls the kernel-class to log its statistics. Kernel calls our statisticsManager-singleton to do the actual upload.

Dependency Injection

Now how can we achieve the same, but without the singleton? For one, since we can't access our singleton object, how do we keep similar functionality? The answer is to pass in all information in the function arguments. We first we remove the inheritance from the singleton class. Since we still need an instance of the former singleton-classes, we'll have to define a member variable. Since kernel apparently needs the SomeManager in the uploadStatistics-function, we'll add it as an function parameter.
See the example C++ sourcecode below:
There is one big difference however. With the second approach, we can create multiple application instances, each using their own kernel & manager instances.
The question which arises is: does this make sense? Well, it depends on the situation. Assume our system streams video. With the second approach, we would be able to instantiate multiple systems, and thus have multiple streams. Assume we add another class, a HttpPostManager, in which we can queue http-post-requests, which are executed in a thread. A callback can be triggered with the post-result. Since it's a Singleton, our Application-instances (and their Kernels and Managers) would use the same HttpPostManager. They would queue their request, which would get executed, and they would get a callback when it's finished. It would actually make sense to only have one, single HttpPostManager so this is a real singleton. Another class perfect for being a singleton would be a Flyweight class.

I prefer dependency injection, mainly because since you just can't get "everything" from "everywhere", you need to be much more aware of what you are doing, and you get a good feeling for which class-variables/functions should be in which class. If you don't you tend to end up passing "everything" as function-parameters, which is destined to end in a big mess.
JSN Teki template designed by JoomlaShine.com