March 1, 2011 (updated November 15, 2018) Dependency Inversion Principle (DIP)
This is a companion discussion topic for the original entry at http://blog.thecodewhisperer.com/permalink/use-your-singletons-wisely-ten-years-later
March 1, 2011 (updated November 15, 2018) Dependency Inversion Principle (DIP)
Excellent read...suffice it to say Dependency Injection does not create coupling but rather reveals it and forces you to rethink your design...hopefully leading to cleaner and more reusable code.
To actually remove the coupling between the classes, one must introduce interfaces. Like, for A to not depend on B, one needs to create an interface with the methods of B that A uses, and have A depend on the interface (and B would trivially implement the interface). Using interfaces and Dependency Injection enables us to break the dependency of class A on the implementation class B. This makes it possible and easy for the "dependency injection code" to use some other implementation class instead of B. One can use any class that implements the interface.
I think you did just show that Dependency Injection makes use of the Singleton Pattern unnecessary. Suppose we discovered or decided that we want to have only one instance of the C class, shared across multiple classes. The "solution" is simple, and you already did it:
C c = new C();
In the Client code, you create one instance of the C class, and then you use it wherever you need it. It's not a problem to enable other classes to use it, as you can pass it into their constructors as you create those classes.
You see, the Singleton Pattern solves the problem of how a class can gain access to "the single standard instance" of something it needs. But when classes have everything they need "handed" to them, through their constructors, then you don't actually have the problem any more. So you don't need the Singleton Pattern, to solve it. You solved the problem using Dependency Injection.