Example for Dependency Inversion
Click here to read more about the concepts of dependency inversion.
Let’s assume that we have a button which shall (de)activate a lamp after a click.
A **simple (non dependency inversion) approach could look like the following one:
public class Lamp {
private boolean isOn;
public void turnOn() {
isOn = true;
}
public void turnOff() {
isOn = false;
}
}
public class Button {
private Lamp lamp;
private boolean isPressed;
public Button(Lamp lamp) {
this.lamp = lamp;
}
public void press() {
isPressed = !isPressed;
if(isPressed) {
lamp.turnOn();
} else {
lamp.turnOff();
}
}
}
In this case the Button class has control over the Lamp class.
But as you can see in the constructor it depends on Lamp - which is a low level module.
So when the methods of the (lower module) Lamp class are changed, we also need to change the methods of the (high module) Button class.
A dependency inversion based solution
Dependency inversion solves this issue as follows:
public interface ButtonClient {
public void turnOn();
public void turnOff();
}
public class Lamp implements ButtonClient {
private boolean isOn;
public void turnOn() {
isOn = true;
}
public void turnOff() {
isOn = false;
}
}
public class Button {
private ButtonClient buttonClient;
private boolean isPressed;
public Button(ButtonClient buttonClient) {
this.buttonClient = buttonClient;
}
public void pressButton() {
isPressed = !isPressed;
if(isPressed) {
buttonClient.turnOn();
} else {
buttonClient.turnOff();
}
}
}
You can see that ButtonClient belongs to the same module as Button. They are both on the same level. The dependency has been inverted.
Furthermore the Button can work with multiple clients which are implementing the interface.
We can also define a module which defines when pressButton is triggered and let the Button class derive from it. So we could go on with this example more and more!