2016-04-26 5 views
1

Bitte verzeihen Sie die mögliche Naivität dieser Frage, aber ich werde mich wirklich verwirrt. Es scheint, dass es eine gute Methode ist, Dependance Injection zu verwenden, um den Code zu entkoppeln, damit Ihre Klassen mit ihren Abhängigkeiten geladen werden. Stellen Sie sich die folgende, wo Klasse Foo eine Abhängung der Klasse Bar hatPHP - wenn Autoloading, warum würden Sie Dependance-Injektion verwenden?

namespace Classes; 

class Foo{ 

    protected barInstance; 

    public function __construct(Bar $barInstance){ 
     $this->barInstance=$barInstance; 
    } 

} 

Allerdings, wenn Sie Ihre Klassen automatisch laden dann sicherlich die folgenden nicht genau das gleiche, ohne die Notwendigkeit von DI?

namespace Classes; 
use Classes/Bar; 

class Foo{ 

    protected barInstance; 

    public function __construct(){ 
     $this->barInstance=new Bar; 
    } 

} 

Danke an alle Antwortenden.

+5

Denn manchmal möchte einige interessante Artikel über DI lesen können Sie keine * neu * 'Bar', sondern eine spezifische * bestehenden * 'Bar'. – ceejayoz

+2

Und weil das Trennen von Problemen (Klasse A, die nicht wissen, wie man eine Instanz von B erstellt), macht es oft einfacher, den Code in einer Unit zu testen (Sie können einfach ein Mock-Objekt übergeben). – JimL

Antwort

0

Dies sind zwei separate Konzepte. Durch das Autoloading können Sie keine Dateien in Ihre Skripte aufnehmen und Ihre Klassen nach Konzept trennen. Was die Abhängigkeitsinjektion angeht, wenn Bar zusätzliche Abhängigkeiten hatte und nicht einfach mit dem neuen Bar(), sondern mit dem neuen Bar ($ dep1, $ dep2) instanziiert werden konnte, dann wäre Ihre Logik zum Erstellen von Bar in Foo's Konstruktor vergraben genauso wie der Konstruktor einer anderen Klasse, die Bar benötigt. Indem Sie den Abhängigkeits-erzeugenden Balken an anderer Stelle invertieren, bevor Sie ihn injizieren, entlasten Sie Foo von dieser zusätzlichen Verantwortung.

2

Autoloading stellt sicher, dass Ihre Klasse definiert ist, wenn Sie darauf verweisen. Die Abhängigkeitsinjektion gibt Ihnen Flexibilität bezüglich der Instanz eines Objekts, das Sie verwenden.

In Ihrem Beispiel, sagen wir, Ihre Bar Klasse verwaltet eine Datenbankverbindung. Nehmen wir an, mit einer neuen Funktion möchten Sie sich manchmal mit einer anderen Datenbank verbinden.

public function __construct(){ 
    $this->barInstance = new Bar(); 
} 

Jetzt müssen Sie Ihre Foo Klasse Refactoring die Änderung zu handhaben, weil Sie fest mit einer Instanz von Bar gekoppelt haben.

public function __construct(Bar $barInstance){ 
    $this->barInstance = $barInstance; 
} 

Nun, ohne Foo zu ändern, kann ich eine andere Instanz von Bar für unterschiedliche Situationen instanziiert. Ein allgemein nützliches Beispiel hierfür sind Komponententests.

In beiden Fällen stellte Autoloading sicher, dass Bar und alle seine eigenen Abhängigkeiten außerhalb von Foo definiert sind.

0

Autoloading und Abhängigkeitsinjektion sind voneinander unabhängige Konzepte.

Der Autoloader kann die Klassen laden. Wenn eine einfache Anweisung wie new Foo() ausgeführt wird, muss der Interpreter die Definition der Klasse Foo kennen. Wenn es es nicht bereits weiß, ruft es die Autoloader auf, bis die Klasse verfügbar wird. Die Autoloader wissen, wo jede Klasse definiert ist und enthalten die korrekte Datei.

Der Abhängigkeitsinjektionscontainer kann Objekte verschiedener Typen erstellen. Es weiß nicht (und kümmert sich nicht) über das Laden von Klassen. Es wird vorausgesetzt, dass new Bar() die Klasse Bar bereits definiert ist (oder es kann automatisch geladen werden).

1

Nehmen Sie das Beispiel mit einer Datenbankverbindung.

Sie haben

public class foo { 
    public function __construct(DbConnectionInterface $db) { ... } 
} 

public class foo2 { 
    public function __construct(DbConnectionInterface $db) { ... } 
} 

... 

und so weiter

In Ihrem "Service-Container" Sie haben etwas wie das

$db = new PdoDbConnection(); // which implements DbConnectionInterface 

$service['foo'] = new foo($db); 
$service['foo2'] = new foo2($db); 

Wenn morgen wollen etwas anderes als gU verwenden, dann Sie müssen nur eine neue Verbindung zur Implementierung der Schnittstelle und dann können Sie Ihre Db-Verbindung an einer Stelle

ändern
$db = new NotPdoDbConnection(); // which implements DbConnectionInterface 

$service['foo'] = new foo($db); 
$service['foo2'] = new foo2($db); 

Wenn Sie die DI nicht verwendet haben, sollten Sie Ihre neue PdoConnection() in allen Klassen, die diese Klasse verwenden, in die neue NotPdoConnection() geändert haben. Aber das Autoload kann Ihnen in diesem Fall nicht viel helfen. Wie von lsklyut gesagt, antwortet er auf zwei verschiedene Konzepte.

sein ein „Dummy“ Fall aber

http://fabien.potencier.org/what-is-dependency-injection.html http://www.martinfowler.com/articles/injection.html