Home > Informatik > Begriffe und Konzepte > Prinzipien der OOP > Prinzip 4

6. Umkehr der Abhängigkeiten

Dependency Inversion Principle

Eine Anwendung wie beispielsweise eine Wetter-App nutzt in der Regel eine Grafikbibliothek des Betriebssystems, um Wetterdaten grafisch darzustellen – etwa in Form eines Balkendiagramms. Dazu ruft sie explizit Funktionen dieser Bibliothek auf.

Wenn jedoch das Fenster der App vergrößert oder verkleinert wird, muss das Betriebssystem die App darüber informieren, damit diese ihre Darstellung anpassen kann. In diesem Fall ruft nicht die App die Bibliothek auf, sondern das Framework des Betriebssystems ruft die App auf – dies ist eine Umkehrung des Kontrollflusses (Inversion of Control bzw. Hollywood-Prinzip: "Don't call us, we'll call you!").

Prinzip: Dependency Inversion Principle

Das Dependency Inversion Principle (DIP) ist ein wichtiges Entwurfsprinzip der objektorientierten Programmierung. Es hilft dabei, Softwaremodule besser voneinander zu entkoppeln und dadurch flexibler und wiederverwendbarer zu machen.

Was bedeutet "Dependency Inversion"?

Wörtlich übersetzt heißt "Dependency Inversion": Umkehrung von Abhängigkeiten. Normalerweise hängt eine Klasse von einer anderen konkreten Klasse ab. Das kann jedoch problematisch werden, wenn man später etwas ändern oder austauschen möchte.

Das DIP besagt daher:

  • Höherstufige Module (z. B. Steuerung, Ablaufplanung) sollen nicht von konkreten Klassen abhängen.
  • Stattdessen sollen sich beide – sowohl die Steuerung als auch die konkrete Umsetzung – an einer gemeinsamen Abstraktion orientieren.

Wenn man mit Abstraktionen (z. B. Basisklassen oder Schnittstellen) arbeitet, kann man die konkrete Umsetzung später leichter austauschen, erweitern oder testen – ohne den Quelltext der Steuerung ändern zu müssen.

Ein einfaches Beispiel (ohne Abstraktion):
public class Lichtschalter
{
   private Lampe lampe;

   public Lichtschalter()
   {
      lampe = new Lampe();
   }

   public void schalteEin()
   {
      lampe.einschalten();
   }
}

public class Lampe
{
   public void einschalten()
   {
      System.out.println("Licht an");
   }
}

Die Klasse Lichtschalter hängt direkt von der konkreten Klasse Lampe ab. Wenn man z. B. stattdessen eine LEDLampe verwenden möchte, muss man die Klasse Lichtschalter ändern. Das ist schlecht für Erweiterbarkeit und Wiederverwendbarkeit.

Besser: Steuerung und Umsetzung voneinander trennen

Wir führen eine gemeinsame Oberklasse ein – oder, sobald bekannt, eine Schnittstelle. Damit hängt der Lichtschalter nicht mehr von einer konkreten Klasse ab, sondern nur noch von der allgemeineren Abstraktion.

public class Lichtschalter
{
   private Lampe lampe;

   public Lichtschalter(Lampe lampe)
   {
      this.lampe = lampe;
   }

   public void schalteEin()
   {
      lampe.einschalten();
   }
}

public class Lampe
{
   public void einschalten()
   {
      System.out.println("Licht an");
   }
}

public class LEDLampe extends Lampe
{
   public void einschalten()
   {
      System.out.println("LED leuchtet");
   }
}

Jetzt entscheidet die aufrufende Klasse, welche Art von Lampe verwendet wird:

Lichtschalter schalter1 = new Lichtschalter(new Lampe());
schalter1.schalteEin();    // Ausgabe: Licht an

Lichtschalter schalter2 = new Lichtschalter(new LEDLampe());
schalter2.schalteEin();    // Ausgabe: LED leuchtet
Was wurde verbessert?

Die Klasse Lichtschalter kennt nicht mehr die konkrete Klasse, sondern nur ein allgemeines Konzept ("Lampe"). Damit kann man die konkrete Umsetzung jederzeit austauschen, ohne etwas ändern zu müssen.

Das ist das Dependency Inversion Principle in der Praxis:
  • Die Abhängigkeit von konkreten Klassen wird "umgedreht".
  • Die Steuerungsschicht ist nicht mehr von der Umsetzung abhängig.
  • Beide orientieren sich an einer gemeinsamen, abstrakten Struktur.
Fazit:

Das DIP fördert flexible und austauschbare Softwarestrukturen. Besonders bei größeren Projekten oder bei automatisierten Tests (z. B. mit Platzhalterobjekten) ist es hilfreich, wenn Klassen nicht direkt von konkreten Implementierungen abhängig sind.

Quellen:

  1. Lahres et al.: Objektorientierte Programmierung, Rheinwerk Computing 2021.
  2. Barnes, Kölling: Java lernen mit BlueJ - Objects first. Pearson-Verlag 2019.
  3. Ullenboom: Java ist auch eine Insel, Rheinwerk Computing 2023.