Firstly, what is the Dependency Inversion Principle?
Definition: One should depend upon abstractions and not concrete instances.
Typically in a software application, high level components need to depend on lower level components. If the low level components are ‘hard-coded’ into the high level components this causes two problems.
The first problem is testability. It becomes very hard or even impossible to write unit tests for your high-level components as they always call low-level components which may rely on things like database connections or files.
2. Code Re-use
The second problem is one of re-usability. It becomes very hard to re-use the high level components as they are coded to specific low level implementations. This limits flexibility and code-reuse.
The solution to these problems is to inject or pass an interface representing the lower level classes to the higher level classes and allow them to call the code on the interface.
This solves the testability problem because these lower-level components can be mocked out and their behaviour pre-set. Thus allowing testing of only the higher-level component code.
It also solves the re-use problem because now different implementations of the lower level code can be passed to the higher level code allowing the higher level code to be re-used.
This type of inversion is sometimes called Dependency Injection and is used whenever a high level component calls a lower level one such as a service requiring access to a database or file system.
The injection is typically handler by an IOC container and not done manually as in our example. Containers such as SPRING and Castle Windsor can be used.
Finally, now you know about the Dependency Inversion Principle, read about the other SOLID principles of Object Orientated design here.