2017-01-28 3 views
3

ich SOLID Prinzipien lese und ich haben hier auf dem „Dependency Inversion Prinzip“ was bedeutet, sollten die Objekte bereits zu Anthere Objekt instanziiert übergeben, die Zusammensetzung bedeutet kann nicht mit Dependency Inversion angewendet werden Prinzip bin richtig? oder gibt es etwas was ich vermisse? UPDATE ************************************************** ** nehme an, Sie eine Klasse, und diese Klasse hat ein Attribut, das zu Anthere Objektreferenz ist, haben wir 2-Lösung (für mich).Dependency Inversion Prinzip und Zusammensetzung

  1. das Objekt außerhalb der Klasse erstellen und an die Klasse übergeben (Abhängigkeit)
  2. Erstellen Sie das Objekt innerhalb der Klasse es selbst (Zusammensetzung).

danke.

+0

Ich sehe hier keinen Widerspruch. Ein Objekt besteht aus einigen anderen Objekten, die ihm im Konstruktor übergeben werden, also was? –

+0

Ich denke, Sie verwechseln Abhängigkeiten zwischen Klassen und Abhängigkeiten zwischen Objekten. Natürlich hängt ein zusammengesetztes Objekt von seinen Komponenten ab. Das bedeutet jedoch nicht, dass Abhängigkeiten zwischen den Klassen bestehen, wenn Sie Abstraktionen (Interfaces) verwenden. –

+0

@FrankPuffer kann ich Komposition mit Dependency-Injektion verwenden? – justsomedev

Antwort

6

Ihre Verwirrung kommt von Ihrem Verständnis der Zusammensetzung. Das Objekt, das einem anderen gehört, hängt von der Lebensdauer des besitzenden Objekts ab. Das bedeutet nicht, dass Sie das eigene Objekt in der besitzenden Klasse erstellen müssen.

Wenn Sie Objekte in einer Klasse erstellen, wird diese Klasse der erstellten Klasse eng gekoppelt. Sie können die Implementierung nicht austauschen, ohne die Klasse zu ändern, die die andere erstellt.

Beispiel: enter image description here

Im Bild oben die Klasse-Client haben, die die Klasse Server verwendet. Nehmen wir an, das ist eine Komposition und der Client hat ein Attribut vom Typ Server.

Wenn Sie eine Instanz der Klasse Server innerhalb der Client-Klasse erstellen, könnte es so aussehen:

public class Client { 
    private Server server; 

    public Client(){ 
     this.server = new Server(); 
    } 
} 

Jetzt können Sie sagen, die Umsetzung des Server austauschen möchten. Sie müssen die Implementierung der Client-Klasse ändern, da die einzige Möglichkeit, sie auszutauschen, darin besteht, eine Instanz einer anderen Klasse (möglicherweise AnotherServer genannt) zu erstellen. Diese

public class Client { 
    private AnotherServer anotherServer; 

    public Client(){ 
     this.anotherServer = new AnotherServer(); 
    } 
} 

zeigt Ihnen, dass die Client-Klasse ist in hohem Maße abhängig von der Klasse Server.

Um die verwendete Implementierung des Servers leicht zu ändern und somit das Verhalten des Clients zu ändern, wäre es besser, den Client aus Abstraktionen (abstrakten Klassen oder Interfaces) zusammenzusetzen. Dies bedeutet, dass Sie das erforderliche Objekt nicht in der besitzenden Klasse erstellen können, da Sie nur konkrete Klassen erstellen können. Klassen erstellen bedeutet, den Konstruktor aufzurufen und von der Klasse abhängig zu sein, die erstellt wurde.

Eine bessere Möglichkeit, Komposition zu erreichen (- der Client besteht aus einem Server -), besteht darin, sie durch eine Setter-Methode oder den Konstruktor zu injizieren. So können Sie Implementierungsklassen hinter einer Schnittstelle verbergen.

Beispiel: enter image description here

Im zweiten Bild, das wir den Kunden aus dem Wissen über die Server des konkrete Umsetzung zu schützen. Es hängt nur von der Serverschnittstelle ab. Diese Abhängigkeit ist nicht so dramatisch, weil der Client die Schnittstelle definiert. Er entscheidet über die benötigte Funktion der Server-Schnittstelle. Um anzuzeigen, dass die Schnittstelle für die Server zum Client gehört, heißt sie "ClientServer".

Um Ihren Client zu erstellen, müssen Sie die konkreten Klassen für die ClientServer-Schnittstelle außerhalb der Klasse erstellen und über den Konstruktor oder eine Setter-Methode einfügen.

... 
FirstServer first = new FirstServer(); 
Client client = new Client(first); 

client.setServer(new SecondServer()); 
... 

So können Sie die verwendete Serverimplementierung im Client auch zur Laufzeit problemlos austauschen.

Dieser Mechanismus wird als Dependency Inversion-Prinzip (DIP) bezeichnet. Aber warum? Die Client-Klasse ist weiterhin von der Server-Schnittstelle abhängig. Wenn sich die Schnittstelle ändert, muss sich der Client ebenfalls ändern. Ja das ist korrekt. Der Kunde entscheidet jedoch, welche Funktionen er in dieser Schnittstelle benötigt. Normalerweise ändert sich die Schnittstelle, wenn der Client sagt, dass sie geändert werden muss. Die Oberfläche ändert sich, weil sich der Client ändert.

Da die konkreten Server "FirstServer" und "SecondServer" die Schnittstelle ClientServer implementieren, sind sie auch von dieser Schnittstelle abhängig. Da die Vererbung eine stärkere Abhängigkeit als die Komposition ist, sind die konkreten Serverklassen stärker abhängig von der Schnittstelle als die Client-Klasse.

Deshalb sind die Abhängigkeiten invertiert. Die konkreten Serverklassen hängen nun vom "Client-ClientServer" -Konglomerat ab.

So die Antwort auf Ihre Frage ist: Sie können DIP nicht erreichen, wenn Sie Ihre Klasse in einer anderen Klasse erstellen. Aber Sie können DIP mit Komposition erreichen, indem Sie eine Schnittstelle definieren und die konkreten Klassen einfügen, die diese Schnittstelle erben.

+0

Wenn ich eine Klasse von .NET Framework verwenden muss. Muss ich es in die Klasse injizieren? – VansFannel

1

from Wikipedia Genommen:

A. High-level-Module nicht auf Low-Level-Module abhängen. Beide sollten von Abstraktionen abhängen.

B. Abstraktionen sollten nicht auf Details abhängen. Details sollten von Abstraktionen abhängen.

Und Sie sagten:

die die Objekte bedeutet, sollten bereits auf ein anderes Objekt instanziiert bestanden

Dependency Inversion Prinzip nichts gegen eine Programmierung Implementierung Detail hat wie Klassenkonstruktoren , die das zu konstruierende Objekt initialisieren sollen.

Sofern Sie keine Konstruktorparameter als Implementierungen anstelle von Abstraktionen definieren und/oder die Abhängigkeiten, die injiziert werden, eine höhere Schicht als die Zielabhängigkeit aufweisen, verstoßen Sie nicht gegen das gesamte Prinzip.

+0

Es wäre toll zu wissen, warum ich einen Downvote bekommen habe, um meine Antwort zu verbessern. Vielen Dank. –

Verwandte Themen