- Dependency Inversion Principle (DIP) – Principle of inverting dependencies in software architecture.
- Inversion Of Control (IoC) – Pattern which uses DIP.
- Dependency Injection (DI) – An Implementation of IoC (but there are many other ways to implement IoC).
- IoC Container – Framework to implement IoC.
Dependency Inversion Principle :-
The higher level modules define interfaces which lower level modules implement. This needs to be done instead of higher level modules depending and using the interfaces which lower level modules expose.
Example :- The computer is a high level device/module. It has an USB port – the interface exposed – to which all other (low level modules) devices e.g iPhone, mouse, Keyboard can plug into. The computer can make use of any device as long as that device can connect to the USB port.
Inversion of Control :-
Provide ways to implement DIP.
- Interface Inversion
- Dependency Creation/Binding Inversion
- Factory methods
- Service Locator
- Dependency Injection
Interface Inversion :-
Suppose we have following classes :-
ATest, BTest1, BTest2, BTest3
BTest1, BTest2 and BTest3 do similar BTest type of work which they have implemented with DoB1Work(), DoB2Work() and DoB3Work() respectively.
Now class ATest needs to call public methods (interface) of BTest1, BTest2 and BTest3 separately. Here Class “ATest” is the consumer and all those B classes are providers.
public class ATest { public void DoSomeAWork() { BTest1 b = new BTest1(); b.DoSomeBWork(); // Do something else } } public class BTest1 { public void DoSomeBWork() { // Do something } }
So here, the consumer (ATest) needs to know about each provider (BTest1, BTest2 and BTest3). The “control” here is in providers’ (B classes) hand because they are defining interfaces (public methods) which the consumer needs to call and need to be changed If the public method changes.
What should really happen – We create an interface IBTest having one method DoBWork() which would be implemented by all the B classes with their own concrete implementation. Here we inverted the control. The control is in consumer’s (Class A) hands now.
Now we end up having something like below in Class ATest.
IBTest bTest = new B1Test();
Now with above, we are still instantiating a concrete class (B1Test) and this makes the ATest (Consumer) dependent on class B1Test (Provider).
Dependency Creation/Binding Inversion patterns
These patterns let creation of dependencies to be done by another class. Following are the ways to do it.
a) Factory Pattern
b) Service Locator
c) Dependency Injection