1

From here: http://www.codingwithoutcomments.com/

If you do use Singletons, try to use dependency injection instead of calling getInstance() from the constructor, use this:

public MyConstructor(Singleton singleton) 
{
     this.singleton = singleton; 
} 

rather than this:

public MyConstructor() 
{
     this.singleton = Singleton.getInstance(); 
}

At the very least, using dependency injection allows you to do some unit testing of the class by adhering to good encapsulation principles.

How is this "dependency injection"? What is the meaning of dependency injection?
Doesn't this defeat the purpose of the Singleton pattern?

Is this supposed to be used for some time and then removed later on?

Aquarius_Girl
  • 18,558
  • 57
  • 191
  • 353

2 Answers2

6

How is this "dependency injection"?

"Dependency injection" means that you explicitly provide an object with references to all other objects that it depends on; that's what the first example does when it passes a reference to the constructor.

The alternative is to implicitly provide the objects that it depends on, by making them globally accessible. That's what the second example does.

The main advantage of dependency injection is that the dependency can be on an abstract interface; there's no need to tie your class to a particular concrete class, or to a particular instance of that class. This makes testing more convenient - your class can be tested in isolation, interacting with "stub" implementations of any interface that it depends on. It also makes it easier to keep track of the dependencies, since they are all explicitly stated in the code.

The main advantages of using globals are that they allow you to write slightly less code, and you don't need to worry about managing dependencies until they become a problem; when they do, you can simply abandon the project and start a new one.

Doesn't this defeat the purpose of the Singleton pattern?

That rather depends on what you think the purpose of the anti-pattern is. It certainly does remove the convenience of a globally-accessible instance; but, assuming the Singleton class does follow the anti-pattern, you still have the assurance that the object you receive is the One True Instance.

Is this supposed to be used for some time and then removed later on?

The singleton should be replaced by a normal class, passed by reference to its dependents, once you need to do things that the anti-pattern prevents (unit testing, multiple instances, subtypes, an abstract interface, etc.). There is little need to remove dependency injection once it's there; you'll only have to put it back again once you find that singletons don't meet your requirements.

Mike Seymour
  • 235,407
  • 25
  • 414
  • 617
1

There are no differences in the codes you provided, and that it not a dependency injection, because you are passing the singleton by value to the constructor (that's a constructor, right?).

If you have to use a singleton, then pass the object it manages to the constructor using a reference :

struct Abase
{
};
struct A : Abase // object of this type is created in the singleton
{
};

struct B
{
  B(Abase &a_) : a(a_)
  {
  }

private:
  Abase & a;
};

//...
B b( Singleton.getInstance() );
//...
BЈовић
  • 57,268
  • 38
  • 158
  • 253
  • `here are no differences in the codes you provided` I posted the link. I didn't write that on my own. Is it wrong? – Aquarius_Girl Feb 08 '12 at 11:25
  • 2
    I don't agree. The first example actually makes dependency injection possible (because it provides a constructor parameter to take the singleton instance), while the second does not. – Niklas B. Feb 08 '12 at 11:27
  • You probably wouldn't call `B b(Singleton.getInstance())` (and the question does not state that it does). You would call `B b(instance)`, because the caller would either be the factory that has direct access to the instance or another object that itself got reference via dependency injection. – Jan Hudec Feb 08 '12 at 11:33
  • From the syntax (but not the question tags), I'm guessing the language is C# or Java, so the argument is being passed by reference. – Mike Seymour Feb 08 '12 at 11:34
  • @NiklasB. That depends on the singleton's implementation. It must return different object, depending whether it's being used in the application, or mock for unit testing. besides there are different kinds of dependency injections. – BЈовић Feb 08 '12 at 11:50
  • @VJovic: In fact, as others have mentioned, in a unit test you wouldn't have to instantiate it with `getInstance()` as an argument, you could use something like `B b(MockedSingleton())`. Probably you wouldn't need the `getInstance` method at all, so as an additional plus, you get rid of the singleton. – Niklas B. Feb 08 '12 at 11:53
  • @NiklasB. That would not even compile, because you are passing objects of different types (take a note that my java experience is low, and c# zero). You probably want to inject dependency like it is done by using a factory, except that in your case a pointer to a mock is returned – BЈовић Feb 08 '12 at 11:58
  • VJovic: Take it as pseudocode. The point is that you *can actually give `B` a mock object*, which you cannot in OP's second code sample. Thus, the samples do actually differ very much in code style and quality. – Niklas B. Feb 08 '12 at 12:00