The Dependency Inversion Principle
it should be pretty clean that reducing dependencies to concrete classes in our code is a good thing. In Face, we've got an OO design principle that formalizes this nothing; it even has a big formal name for it.. 'the Dependency Inversion Principle'.
At first, this principle sounds a lot like " program to an interface, not a implementation" right?. it is similar; however, the Dependency Inversion Principle makes an even strong statement about abstraction. It suggests that our high level components should not depend on our low
level components; rather they should bother depend on abstractions.
But what the heck does that mean?
Well, let's start by looking again at the first pizza store diagram. Pizza store is our "high-level component" and the pizza implementations are our "low-level components", and clearly the Pizza Store is dependent on the concrete pizza classes.
Now this principle tells us we should instead write our code so that we are depending on abstractions, not concrete classes. That goes for both our high level models and our low-level modules.
But how do we do this? lets think about how we'd apply this principle to our very dependent Pizza-store implementation.
Applying the principle
Now the main problem with the Very Dependent PizzaStore is that it depends on every type of pizza because it actually instantiates concrete types in its orderPizza() method.
When you directly instantiate an object, you are depending on its concrete class.
While we've created an abstraction, Pizza we're never-less creating concrete pizzas in the code, so we don't get a lot of leverage out of this abstraction.
How can we get those instantiations out of the orderPizza method? well, as we know, the Factory Method allows us to do just that.
So after we've applied the Factory Method, our 2nd diagram looks like this:
After applying the Factory Method, you'll notice that our high-level component, the PizzaStore, and our low-level components, the pizzas, both depend on Pizza, the abstraction. Factory Method is not the only technique for adhering to the Dependency Inversion Principle, but it is one of the more powerful ones.
Where is the "inversion" in Dependency Inversion Principle?
The "inversion" in the name Dependency Inversion Principle is there because it inverts the way you typically might think about your OO design. Look at the diagram on the previous page, notice that the low-level components now depend on a higher level abstraction. Likewise, the high level component is also tied to the same abstraction. So, the top-to-bottom dependency chart we drew first, has inverted itself, with both high level and low-levels now depending on the abstraction.
A few guidelines to help you avoid violating the principle.
- No variable should hold a reference to a concrete class.
- No class should derive from a concrete class.
- No method should override an implemented method of any of its base classes.