2015-09-29 15 views
7

Sto cercando di capire l'integrazione delle dipendenze in PHP e vedo che ci sono due modi per farlo in Laravel.Qual è la differenza tra questi due tipi di iniezioni del costruttore in PHP?

Cerchiamo quindi di dire che ho una classe Foo in questo modo:

class Foo{ 

} 

Ora ho una classe chiamata Bar che dipende Foo così ho potuto fare qualcosa di simile:

class Bar{ 
    protected $foo; 
    public function __construct() 
    { 
     $this->foo = new Foo(); 
    } 
} 

Ma in laravel, mi sono imbattuto in termini come typehinting e di riflessione, che mi permettono di fare questo:

class Bar{ 
    protected $foo; 
    public function __construct(Foo $foo) 
    { 
     $this->foo = $foo; 
    } 
} 

Quello che sto cercando di capire è la differenza tra questi due. Sono totalmente identici? E c'è una ragione specifica che dovrei preferire rispetto all'altra?

PS: Sono newbie e non sono sicuro se sto usando il gergo in correttamente alla domanda.

+9

Il primo esempio è molto difficile da testare, perché non è possibile simulare Foo all'interno di Bar; il secondo si chiama Dependency Injection (DI), e ti permette di prendere in giro Foo quando stai testando Bar –

+3

possibile duplicato di [Cos'è l'iniezione delle dipendenze?] (http://stackoverflow.com/questions/130794/what-is- dipendenza-iniezione) – Gal

+5

Il secondo elimina anche la necessità che Foo sia in realtà un'istanza di Foo, ma gli consente di essere un Foo, o un'istanza di qualsiasi classe che estende Foo (il tipo di suggerimento che lo impone) .... accoppiamento libero , perché non sei più vincolato a un vero Foo –

risposta

1

principalmente scende al accoppiamento di codice.

class Foo { 
    public function __construct() { 
     new Bar; 
    } 
} 

Questa coppie molto specifici Bar a questo specifico Foo. Non c'è modo di modificare cheBar ottiene istanziato senza dover riscrivere il codice. Ciò significa anche che lo Foo deve conoscere le dipendenze di Bar. Forse oggi Bar può essere istanziato con solo new Bar. Ma forse domani stai refactoring Bar e ora devi istanziarlo con new Bar($database). Ora devi anche riscrivere Foo per adattarlo.

Ecco dove la dipendenza iniettabile viene fornito in (quanto sopra è non iniezione di dipendenza, non sei iniettando nulla):

class Foo { 
    public function __construct(Bar $bar) { } 
} 

Questo Foo dichiara semplicemente che ha bisogno di un oggetto con le caratteristiche di Bar su istanziazione. Ma Foo non ha bisogno di sapere nulla su come Bar avvenne per essere, quali sono le sue dipendenze sono o cosa che fa. L'unica cosa che si aspetta da Bar è un'interfaccia definita public, qualsiasi altra cosa è irrilevante. In effetti, per ottenere una flessibilità ancora maggiore, è possibile utilizzare uno interface invece di una dipendenza di classe concreta qui.

Dipendenza iniezione permette di ripudiare i dettagli concreti di classi da altro codice. Ti consente di avere un luogo centrale in cui vengono istanziate le classi, che è un luogo in cui devi conoscere e considerare dettagli concreti sulle classi che stai creando. Ad esempio, questo può essere un contenitore di iniezione di dipendenza. Non vuoi diffondere la logica di istanziazione di classe dappertutto, perché come detto sopra, quella logica potrebbe cambiare, e quindi devi riscrivere il codice dappertutto.

require_once 'Foo.php'; 
require_once 'Bar.php'; 

$foo = new Foo(new Bar); 

Il codice sopra è dove è stata decisa cheBar ottiene iniettati Foo. È anche il posto che deve preoccuparsi delle dipendenze di Bar. Nota che il caricamento e l'istanziazione delle dipendenze sono l'unica cosa che fa questo codice. È banale modificare solo questa parte di codice, se necessario, senza dover toccare Foo o Bar, che potrebbe essere piena di logica aziendale complessa.

Il codice con ingerenza di dipendenza consente inoltre di separare l'app e di combinarla in modo flessibile. Ad esempio per scopi di test. O semplicemente per riutilizzare le diverse componenti in modo flessibile in diversi contesti.

Vedere anche How Not To Kill Your Testability Using Statics.

+0

Grazie mille per questa risposta dettagliata. Lo apprezzo. :) – Rohan

Problemi correlati