Abstract factories for injecting runtime dependencies in complex hierarchies-Collection of common programming errors
Given the following class hierarchy
- ClassA needs ClassB
- ClassB needs ClassC
we get a dependency graph like this:
ClassA --> ClassB --> ClassC
so if we use DI we inject ClassC into ClassB and ClassB into ClassA.
But now let’s say ClassC is a runtime dependency (for example some kind of strategy). The proposed way to inject a runtime dependency is to introduce an abstract factory like a
ClassCFactory
Now we can inject ClassCFactory into ClassB and get the following graph
ClassA --> ClassB --> ClassCFactory
Now we have a method in ClassB which we can call to let the factory do its work. For example
ObjB.SelectC(MyRuntimeValue)
But now in our application we do not know anything about ClassB (perhaps there are some more layers involved). One solution might be to have a SelectC in ClassA
ObjA.SelectC(MyRuntimeValue) -(calls)-> ObjB.SelectC(MyRuntimeValue)
or we simply violate the Law Of Demeter and do something like
ObjA.ObjB.SelectC(MyRuntimeValue)
I think everyone agrees that the second solution is not the way to go. But the first solution also has several drawbacks, especially if we have more layers in between.
We could also pull up the factory one level to create ClassB, but is ClassB really a runtime dependency? What solutions do you suggest? Or is it even a bad class design?
IMHO it is always better to have a dependency on what the object actually needs to do its work and not on a factory which creates the object needed. But with this thought in mind a DI container would be useless…