When my wife recently pointed me to an article by Jim Weirich about Dependency Injection (DI), one of my first thoughts was, “how is this different from the Abstract Factory (AF) pattern?” So I did some searching and found a brief comment from Martin Fowler:
If you have multiple ways to construct a valid object, it can be hard to show this through constructors, since constructors can only vary on the number and type of parameters. This is when Abstract Factory Methods come into play, these can use a combination of private constructors and setters to implement their work. The problem with classic Factory Methods for components assembly is that they are usually seen as static methods, and you can’t have those on interfaces. You can make a factory class, but then that just becomes another service instance. A factory service is often a good tactic, but you still have to instantiate the factory using one of the techniques here.
Fowler’s objections with respect to static methods on interfaces are specific to java, and don’t apply in python or ruby, since neither have native interfaces. Yet I see DI used in both ruby and python, so I still feel like there has to be another difference.
Next I found some interesting thoughts at Stack Overflow, but none of the responses shed a clear light on the subject for me.
What finally got the light in my head to switch on, oddly enough, was an article by Jakob Jenkov. After reading Jenkov, I understood that both AF and DI are responsible for creating instances of objects. Furthermore, they both decouple the class requesting object creation from having to know any details about the created object that they’ll receive. Where they’re different, is that when AF is being used, the class desiring the creation of an object needs to know about—and send a message to—an AF, whereas with DI, the class desiring the creation of an object is simply handed that object during it’s own initialization. To put it another way, the object on which it relies is “injected” into it at its own creation. This is the inversion, that rather than the class needing to ask for an object to be created, it is instead handed the object.
|Is responsible for instantiating classes?||Yes||Yes|
|Class needs to know details of the created object?||No||No|
|Class needs to explicity request creation of desired object?||No||Yes|
|Class is dependent upon the DI/Factory that creates objects on its behalf?||No||Yes|
Now that the light was on, I re-read the first few references, and I found that may of them made more sense. Funny how that works.