Component Based Development/DI

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Zur Klärung der Frage, was Dependency Injection (DI) soll zuerst beschrieben werden, welche Art von Abhängigkeit (Dependency) hiermit gemeint ist.

In DI steht das D für Abhängigkeiten zwischen Klassen bzw. genauer zwischen den korrespondierenden Objekten.

Da in der Regel komplexere Objekte Funktionalitäten anderer Objekte benötigen, haben Sie diese Objekte in Membervariablen (Objektvariablen) gespeichert. z.B. (modifiziert aus M. Fowler: Inversion of Control Containers and the Dependency Injection pattern, 2004 http://martinfowler.com/articles/injection.html) :

..
public class MovieLister {
  ...
  private MovieFinder ;
  ....
  
  public Movie[] moviesDirectedBy(String directorName) {
        List<Movie> allMovies = finder.findAll();
        for (Movie movie : allMovies){
            if (!movie.getDirector().equals(directorName)) {
               it.remove();
            }
        }
        return allMovies.toArray();
    }
}

Die Methode moviesDirectedBy verwendet hier ein Objekt von Typ MovieFinder. Man sagt MovieFinder ist abhängig von MovieLister.

Der MovieFinder ist ein Interface, für die es eine Vielzahl von Implementierungen (DBMovieFinder, ColonDelimiterMovieFinder) geben könnte.

public interface MovieFinder {
  List<Movie> findAll();
}


Wenn nun aber direkt im Konstruktor des MovieLister eine konkrete MovieFinder-Instanz erzeugt, ist diese Wiederverwertbarkeit nicht gegeben, z.B durch:

class MovieLister
...
  private MovieFinder finder;
  public MovieLister() {
    finder = new ColonDelimitedMovieFinder("movies1.txt");
  }

Der MovieLister ist fest mit einer Implementierung des MovieFinder (ColonDelimitedMovieFinder) verbunden. Dies führt zu einer starken Kopplung. Hierdurch ist aber die Methode moviesDirectedBy bzw. der MovieLister nicht mehr für alle möglichen Ausprägungen (Implementierungen) des MovieFinder nutzbar. Außerdem lässt sich die Methode moviesDirectedBy nicht mehr testen, ohne gleichzeitig den ColonDelimitedMovieFinder mit zu testen. Ein weiterer Nachteil ist das die Abhängigkeit vom MovieLister zum MovieFinder nicht in den Methoden-Signaturen (denke an Javadoc) erkennbar ist, sondern nur in der Implementierung.

Eine Lösung des Problems ist die Abhängigkeit z4 der 26n2reten 0*3e0ent5er4ng von außen hinein zugeben, z.B. über den Konstruktor (Constructor Injection). Nicht die die Klasse selbst kümmert sich um die Auflösung der konkret genutzten Implementierung des Interface. Sie wird von außen injiziert. Daher der Name "Dependency (Abhängigkeit) Injection (Injizieren)".


  public MovieLister(MovieFinder finder) {
    this.finder = finder;
  }

Hier wird aus der Konstruktor-Signatur die Abhängigkeit ersichtlich.


Dies ist die Grundlage von Dependency Injection (DI). Dabei ergeben sich folgende Vorteile:

  • Bessere Wiederverwertbarkeit
  • Schwächen der Kopplung zwischen den Komponenten
  • Isoliertes Testen (injizieren von Mock-Objekten) wird möglich
  • Erkennen der Abhängigkeit in der Methoden-, bzw. Konstruktor-Signatur.