You can still "cache" values in regular instance variables, without them being static.
Of course you can, but then you can't ensure every new instance uses the same resources (a database connection for example). Unless you use something like a registry to transport those resources.
What if you had to make an adapter for your adapter? You'd have to update the singleton calls to your 1st adapter to use one of the "sub" adapters. With object composition each 1st adapter object holds a sub-adapter as an instance variable. The code that uses the 1st adapter doesn't know about sub-adapters. The reason you are experiencing confusion is because you have not had to change code and felt the pain of having the stuff hard wired, therefore you don't see the benefit.
This is a good point, however that adapter will basically instance the old adapter class, which contains the static connection, and so it's a non-issue. Pay attention that I said the adapter class is not a singleton, but the database connection is.
"it helps that I separated the dependencies to their own logical scopes [objects] instead of condensing them all in a generic global state."
The objects are the scopes.
Actually, I meant it as I wrote it. Static properties / methods belong to the class, not the object and so that is the scope I am referring to.
I guess I am wondering why DB and Cache are different that the many other objects in the system. They certainly would fall under "common objects" that are candidates for using a Registry.
They are different because the encapsulate separate concerns. The fact that they need to be accessed globally in the application doesn't make them "common" objects - just the opposite! they're very unique.
I have actually gone the opposite direction ... However I have been stung by it many times ... Using a Registry makes it become "logical" in my way of thinking
Well I can't argue with this of course. We each draw from our own personal experiences and form our own biases.