Injekce závislosti
Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od
verze recenzované 14. listopadu 2019; kontroly vyžadují
16 úprav .
Dependency injection (DI ) je proces poskytování externí závislosti softwarové komponentě . Jde o specifickou formu „ inverze řízení “ ( anglicky Inversion of control, IoC ), když je aplikována na správu závislostí. V plném souladu s principem jediné odpovědnosti přenechává objekt péči o budování závislostí, které vyžaduje, externímu, speciálně navrženému pro tento obecný mechanismus [1] .
Vložení skutečné závislosti
Při použití vzoru "injekce závislosti" je objekt pasivní a nepodniká vůbec žádné kroky k určení závislostí, ale poskytuje pro to nastavovače a/nebo přijímá argumenty ve svém konstruktoru, přes které se vkládají závislosti [1] .
Jak to funguje
Práce rámce pro vkládání závislostí je popsána následovně. Aplikace, bez ohledu na design, běží uvnitř IoC kontejneru poskytovaného frameworkem. Některé objekty v programu jsou stále vytvářeny obvyklým způsobem programovacího jazyka, některé jsou vytvářeny kontejnerem na základě konfigurace, která je mu poskytnuta.
Podle konvence, pokud objekt potřebuje přistupovat k určité službě , přebírá odpovědnost za přístup k této službě: buď získá přímý odkaz na umístění služby, nebo se dostane ke známému „lokátoru služeb “ a požaduje odkaz na implementaci určitého typu služby. Pomocí vkládání závislostí objekt jednoduše zpřístupní vlastnost, která je schopna uložit odkaz na požadovaný typ služby; a při vytvoření objektu se do této vlastnosti (pole) pomocí nástrojů prostředí automaticky vloží odkaz na implementaci požadovaného typu služby.
Vkládání závislostí je flexibilnější, protože je snazší vytvořit alternativní implementace daného typu služby a poté určit, která implementace by měla být použita, například v konfiguračním souboru , aniž by bylo nutné měnit objekty, které tuto službu používají. To je užitečné zejména při testování jednotek, protože je velmi snadné vložit implementaci služby „ stub “ do testovaného objektu.
Na druhou stranu nadměrné používání vkládání závislostí může způsobit, že aplikace jsou složitější a obtížněji se udržují: protože k tomu, aby programátor pochopil chování programu, musí se podívat nejen na zdrojový kód, ale také na konfiguraci, a konfigurace je obvykle neviditelná pro IDE , které podporuje analýzu a refaktorování odkazů, pokud není výslovně uvedeno pro podporu rámců pro vkládání závislostí
.
Příklady kódu
Při použití vkládání závislostí zpravidla existuje konfigurační mechanismus nebo architektura, která určuje vhodnost výběru té či oné implementace v závislosti na cílech.
Příklady v různých jazycích
<?php
/**
* Třída konfigurace databáze
*/
třídy DbConfiguration
{
soukromý $hostitel ;
soukromý $port ;
private $username ;
soukromé $heslo ;
veřejná funkce __construct ( řetězec $hostitel , int $port , řetězec $uživatelské jméno , řetězec $heslo )
{
// celá pointa Di je v řádcích níže
$this -> host = $hostitel ;
$this -> port = $port ;
$this -> username = $username ;
$toto -> heslo = $heslo ;
}
veřejná funkce getHost ()
{
return $this -> host ;
}
veřejná funkce getPort ()
{
return $this -> port ;
}
veřejná funkce getUsername ()
{
return $this -> uživatelské jméno ;
}
veřejná funkce getPassword ()
{
return $this -> heslo ;
}
}
/**
* Třída připojení k databázi
*/
třídy DbConnection
{
privátní $konfigurace ;
veřejná funkce __construct ( DbConfiguration $config )
{
// celá podstata Di je v řádku níže
$this -> konfigurace = $config ;
}
veřejná funkce getDsn ()
{
// poznámka: toto není skutečné dsn, skutečné oddělovače dsn jsou jiné
návrat sprintf (
'%s:%s@%s:%d' ,
$this -> konfigurace -> getUsername (),
$this -> konfigurace -> getPassword (),
$this -> konfigurace -> getHost (),
$this -> konfigurace -> getPort ()
);
}
}
// vytvoří objekt konfigurace databáze předáním parametrů konstruktoru
$config = new DbConfiguration ( 'localhost' , 3306 , 'uživatelské jméno' , 'heslo' );
// vytvoří objekt připojení k databázi odesláním konfiguračního objektu konstruktoru
// použití Di způsobí, že kód bude volně propojen
$connection = new DbConnection ( $config );
Příklad kódu Java
public interface ICar {
public float getSpeed ();
public void setPedalPressure ( finální float PEDAL_PRESSURE );
}
public interface IEngine {
public float getEngineRotation ();
public void setFuelConsumptionRate ( final float FUEL_FLOW );
}
Bez použití injekce závislosti
public class DefaultEngineImpl implementuje IEngine {
private float engineRotation = 0 ;
public float getEngineRotation () {
return engineRotation ;
}
public void setFuelConsumptionRate ( final float FUEL_FLOW ) {
engineRotation = ... ;
}
}
public class DefaultCarImpl implementuje ICar {
private IEngine engine = new DefaultEngineImpl ();
public float getSpeed () {
return engine . getEngineRotation () * ... ;
}
public void setPedalPressure ( final float PEDAL_PRESSURE ) {
motor . setFuelConsumptionRate ( ... );
}
}
public class MyApplication {
public static void main ( String [] args ) {
DefaultCarImpl car = new DefaultCarImpl ();
auto . setPedalPressure ( 5 );
plovoucí rychlost = auto . getSpeed ();
Systém . ven . println ( "Rychlost auta je" + rychlost );
}
}
Ruční vstřikování závislosti
public class DefaultCarImpl implementuje ICar {
private IEngine engine ;
public DefaultCarImpl ( final IEngine engineImpl ) {
engine = engineImpl ;
}
public float getSpeed () {
return engine . getEngineRotation () * ... ;
}
public void setPedalPressure ( final float PEDAL_PRESSURE ) {
motor . setFuelConsumptionRate ( ... );
}
}
public class CarFactory {
public static ICar buildCar () {
return new DefaultCarImpl ( new DefaultEngineImpl ());
}
}
public class MyApplication {
public static void main ( String [] args ) {
ICar car = CarFactory . buildCar ();
auto . setPedalPressure ( 5 );
plovoucí rychlost = auto . getSpeed ();
Systém . ven . println ( "Rychlost auta je" + rychlost );
}
}
Dependency Injection with Framework
<service-point id= "CarBuilderService" >
<invoke-factory>
<construct class= "Car" >
<service> DefaultCarImpl
</service>
<service> DefaultEngineImpl
</service>
</construct>
</invoke-factory>
< /service-point>
/** Implicitní implementace **/
public class MyApplication {
public static void main ( String [] args ) {
Service service = ( Service ) DependencyManager . get ( "CarBuilderService" );
ICar auto = ( ICar ) služba . getService ( Car . class );
auto . setPedalPressure ( 5 );
plovoucí rychlost = auto . getSpeed ();
Systém . ven . println ( "Rychlost auta je" + rychlost );
}
}
Viz také
Poznámky
- ↑ 12. Martin , 2008 .
Literatura
Odkazy