Component Based Development/DI
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.