Inyección de dependencia
La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la
versión revisada el 14 de noviembre de 2019; las comprobaciones requieren
16 ediciones .
La inyección de dependencia (DI ) es el proceso de proporcionar una dependencia externa a un componente de software . Es una forma específica de " inversion of control " ( inglés Inversion of control, IoC ) cuando se aplica a la gestión de dependencias. En plena conformidad con el principio de responsabilidad única, el objeto deja el cuidado de construir las dependencias que requiere a un mecanismo externo, especialmente diseñado para este general [1] .
Inyección de dependencia real
Cuando se usa el patrón de "inyección de dependencia", el objeto es pasivo y no toma ningún paso para determinar las dependencias, pero proporciona setters para esto y/o acepta argumentos en su constructor a través de los cuales se inyectan las dependencias [1] .
Cómo funciona
El trabajo del marco de inyección de dependencia se describe a continuación. La aplicación, independientemente del diseño, se ejecuta dentro del contenedor IoC proporcionado por el marco. Algunos de los objetos en el programa todavía se crean de la forma habitual del lenguaje de programación, algunos son creados por el contenedor en función de la configuración que se le proporciona.
Por convención, si un objeto necesita acceder a un servicio en particular , el objeto asume la responsabilidad de acceder a ese servicio: obtiene una referencia directa a la ubicación del servicio o va a un conocido "localizador de servicios " y solicita una referencia a la implementación de un tipo particular de servicio. Usando la inyección de dependencia, un objeto simplemente expone una propiedad que puede almacenar una referencia al tipo de servicio deseado; y cuando se crea un objeto, se inserta automáticamente una referencia a la implementación del tipo de servicio deseado en esta propiedad (campo) utilizando las herramientas del entorno.
La inserción de dependencias es más flexible porque se vuelve más fácil crear implementaciones alternativas de un tipo de servicio determinado y luego especificar qué implementación se debe usar, por ejemplo, en un archivo de configuración , sin cambiar los objetos que usan ese servicio. Esto es especialmente útil en las pruebas unitarias porque es muy fácil insertar una implementación " stub " del servicio en el objeto bajo prueba.
Por otro lado, el uso excesivo de la inyección de dependencia puede hacer que las aplicaciones sean más complejas y difíciles de mantener: ya que, para comprender el comportamiento de un programa, un programador necesita mirar no solo el código fuente, sino también la configuración, y la configuración suele ser invisible para el IDE , que admite análisis de enlaces y refactorización a menos que se especifique explícitamente para admitir marcos de inyección de dependencia
.
Ejemplos de código
Cuando se utiliza la inyección de dependencias, por regla general, existe un mecanismo o arquitectura de configuración que determina la conveniencia de elegir una u otra implementación, dependiendo de los objetivos.
Ejemplos en varios idiomas
Ejemplo de código PHP
<?php
/**
* Clase de configuración de base de datos
*/
clase DbConfiguration
{
host privado $ ;
puerto privado $ ;
privado $ nombre de usuario ;
$contraseña privada ;
función pública __construct ( cadena $host , int $puerto , cadena $nombre de usuario , cadena $contraseña )
{
// todo el punto de Di está en las líneas de abajo
$esto -> host = $host ;
$esto -> puerto = $puerto ;
$este -> nombre de usuario = $nombre de usuario ;
$esto -> contraseña = $contraseña ;
}
función pública getHost ()
{
devuelve $este -> host ;
}
función pública getPort ()
{
devuelve $este -> puerto ;
}
función pública getUsername ()
{
devuelve $este -> nombre de usuario ;
}
función pública obtener contraseña ()
{
devuelve $esto -> contraseña ;
}
}
/**
* Clase de conexión de base de datos
*/
clase DbConnection
{
$configuración privada ;
función pública __construct ( DbConfiguration $config )
{
// toda la esencia de Di esta en la linea de abajo
$esto -> configuración = $config ;
}
función pública getDsn ()
{
// nota: este no es un dsn real, los delimitadores de dsn reales son diferentes
volver sprintf (
'%s:%s@%s:%d' ,
$this -> configuración -> getUsername (),
$this -> configuración -> getPassword (),
$esto -> configuración -> getHost (),
$this -> configuración -> getPort ()
);
}
}
// crea un objeto de configuración de base de datos pasando parámetros al constructor
$config = new DbConfiguration ( 'localhost' , 3306 , 'username' , 'password' );
// crea un objeto de conexión a la base de datos enviando el objeto de configuración al constructor
// usar Di hace que el código se acople débilmente
$conexión = nueva DbConnection ( $config );
Ejemplo de código Java
interfaz pública ICar {
public float getSpeed ();
public void setPedalPressure ( final float PEDAL_PRESSURE );
}
interfaz pública IEngine {
public float getEngineRotation ();
public void setFuelConquisitionRate ( final float FUEL_FLOW );
}
Sin usar inyección de dependencia
clase pública DefaultEngineImpl implementa IEngine {
private float engineRotation = 0 ;
public float getEngineRotation () {
return engineRotation ;
}
public void setFuelConquisitionRate ( final float FUEL_FLOW ) {
engineRotation = ... ;
}
}
clase pública DefaultCarImpl implementa ICar {
motor IEngine privado = new DefaultEngineImpl ();
getSpeed public float () { motor de retorno . getEngineRotation () * ... ; }
public void setPedalPressure ( final float PEDAL_PRESSURE ) {
motor . establecer Tasa de Consumo de Combustible ( ... );
}
}
public class MyApplication {
public static void main ( String [] args ) {
DefaultCarImpl car = new DefaultCarImpl ();
coche _ establecerPresiónPedal ( 5 );
velocidad de flotación = coche . obtenerVelocidad (); sistema _ fuera _ println ( "La velocidad del carro es" + velocidad ); } }
Inyección de dependencia manual
clase pública DefaultCarImpl implementa ICar {
motor privado IEngine ;
public DefaultCarImpl ( IEngine final engineImpl ) { motor = engineImpl ; }
getSpeed public float () { motor de retorno . getEngineRotation () * ... ; }
public void setPedalPressure ( final float PEDAL_PRESSURE ) {
motor . establecer Tasa de Consumo de Combustible ( ... );
}
}
public class CarFactory {
public static ICar buildCar () {
return new DefaultCarImpl ( new DefaultEngineImpl ());
}
}
public class MyApplication {
public static void main ( String [] args ) {
ICar car = CarFactory . construirCoche ();
coche _ establecerPresiónPedal ( 5 );
velocidad de flotación = coche . obtenerVelocidad (); sistema _ fuera _ println ( "La velocidad del carro es" + velocidad ); } }
Inyección de dependencia con un marco
< id del punto de servicio= "ServicioConstructordeCoches" >
<invocar-fábrica>
< clase de construcción= "Coche" >
<servicio> DefaultCarImpl
</service>
<servicio> DefaultEngineImpl
</service>
</construct>
</invoke-factory>
< /punto-de-servicio>
/** Implementación implícita **/
public class MyApplication {
public static void main ( String [] args ) {
Service service = ( Service ) DependencyManager . obtener ( "Servicio de construcción de automóviles" );
ICar coche = ( ICar ) servicio . getService ( Coche . clase );
coche _ establecerPresiónPedal ( 5 );
velocidad de flotación = coche . obtenerVelocidad (); sistema _ fuera _ println ( "La velocidad del carro es" + velocidad ); } }
Véase también
Notas
- ↑ 12 Martín , 2008 .
Literatura
Enlaces