Mateusz Wajnberger

Dependency  Inversion Principle

Zasada odwrócenia zależności polega na używaniu interfejsu polimorficznego wszędzie tam, gdzie jest to możliwe, szczególnie w parametrach funkcji. Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych. Oba powinny zależeć od abstrakcji.  

Przykład 

Jako przykład weźmiemy zespół programistów, którzy pracują nad projektem. Klasy „BackendDeveloper” oraz „FrontendDeveloper” są modułami niskopoziomowymi, natomiast klasa „Project” jest modułem wysoko poziomowym. W naszym przykładzie widzimy, że moduł wysokopoziomowy jest zależny od modułów niskopoziomowych co zaprzecza omawianej zasadzie DIP. 

public class BackendDeveloper {

public void writeJava() {
System.out.println("I'm writing Java code");
}
}
public class FrontendDeveloper {

public void writeJavaScript() {
System.out.println("I'm writing JavaScript code");
}
}
public class Project {

private BackendDeveloper backendDeveloper = new BackendDeveloper();
private FrontendDeveloper frontendDeveloper = new FrontendDeveloper();

public void implement() {
backendDeveloper.writeJava();
frontendDeveloper.writeJavaScript();
}
}

Zastosowanie Dependency Inversion Principle

Chcąc zastosować DIP w naszym kodzie, możemy stworzyć interfejs. Niskopoziomowe moduły implementując interfejs, będą zależne od abstrakcji. 

public interface Developer {

public void develop();
}
public class BackendDeveloper implements Developer {

@Override
public void develop() {
this.writeJava();
}

public void writeJava() {
System.out.println("I'm writing Java code");
}
}
public class FrontendDeveloper implements Developer {

@Override
public void develop() {
this.writeJavaScript();
}

public void writeJavaScript() {
System.out.println("I'm writing JavaScript code");
}
}

W klasie „Project” usuwamy zależność od niskopoziomowych modułów. Udało się w ten sposób odwrócić zależności. Teraz zgodnie z zasadą Dependency Inversion Principle, moduł wysokopoziomowy nie zależy już od modułu niskopoziomowego, a zależy od abstrakcji.

public class Project {

public void implement(Developer dev) {
dev.develop();
}
}

Podsumowanie

Głównym celem stosowania DIP jest rozdzielenie zależności modułów wysokopoziomowych od niskopoziomowych poprzez stosowanie abstrakcji. Dobrym pomysłem jest wprowadzenie dodatkowego typu abstrakcyjnego, tak byśmy bazowali na czymś bardziej ogólnym co pozwoli nam na zmniejszenie zależności pomiędzy klasami. 

mateusz.wajnberger@gmail.com