Respuesta

18

Dependencia de inyección se refiere al patrón de decirle a una clase cuáles serán sus dependencias, en lugar de requerir que la clase sepa dónde encontrar todas sus dependencias.

Así, por ejemplo, que van desde la siguiente:

public class UserFetcher { 
    private final DbConnection conn = 
     new DbConnection("10.167.1.25", "username", "password"); 

    public List<User> getUsers() { 
     return conn.fetch(...); 
    } 
} 

a algo como esto:

public class UserFetcher { 
    private final DbConnection conn; 

    public UserFetcher(DbConnection conn) { 
     this.conn = conn; 
    } 

    public List<User> getUsers() { 
     return conn.fetch(...); 
    } 
} 

Esto reduce el acoplamiento en el código, que es especialmente útil si quieres prueba de la unidad UserFetcher. Ahora, en lugar de UserFetchersiempre ejecutándose en una base de datos que se encuentra en 10.167.1.25, puede pasar un DbConnection a una base de datos de prueba. O, incluso más útil en una prueba rápida, puede pasar una implementación o subclase de DbConnection que ni siquiera se conecta a una base de datos, ¡simplemente descarta las solicitudes!

Sin embargo, este tipo de inyección de dependencias primitiva hace cableado (que proporciona un objeto con sus dependencias) más difícil, porque se ha sustituido el acceso a la dependencia mediante una variable global (o un objeto de instancia local) con el paso de la dependencia a través de todo el gráfico de objetos.

Piense en un caso en el que UserFetcher es una dependencia de AccountManager, que es una dependencia de AdminConsole. Entonces AdminConsole necesidades pasan a la instancia DbConnection a AccountManager y AccountManager tiene que pasar a UserFetcher ... aunque ninguno de ellos, ni AdminConsoleAccountManager necesidad de utilizar el DbConnection directamente!

Un inversión de control contenedor (primavera, Guice, etc) que tiene como objetivo hacer más fácil la inyección de dependencias conectando automáticamente (siempre) las dependencias. Para hacer esto, le dice a su contenedor IoC una vez cómo proporcionar un objeto (en Spring, esto se llama bean) y siempre que otro objeto solicite esa dependencia, será provisto por el contenedor.

Así que nuestro último ejemplo podría tener este aspecto con Guice, si usamos la inyección de constructor:

public class UserFetcher { 
    private final DbConnection conn; 

    @Inject //or @Autowired for Spring 
    public UserFetcher(DbConnection conn) { 
     this.conn = conn; 
    } 

    public List<User> getUsers() { 
     return conn.fetch(...); 
    } 
} 

y tenemos que configurar el contenedor IoC. En Guice esto se hace a través de una implementación de Module; en Spring configura un contexto de aplicación , a menudo a través de XML.

public class MyGuiceModule extends AbstractModule {  
    @Override 
    public void configure() { 
     bind(DbConnection.class).toInstance(
      new DbConnection("localhost", "username", "password")); 
    } 
} 

Ahora, cuando UserFetcher se construye mediante Guice o primavera, la DbConnection se proporciona automáticamente.

Guice tiene a really good Wiki article sobre la motivación detrás de la inyección de dependencia y el uso adicional de un contenedor IoC. Vale la pena leer todo el camino.

El patrón estrategia es sólo un caso especial de inyección de dependencias, donde se inyecta lógica en lugar de un objeto (a pesar de que en Java, la lógica se encapsula en un objeto). Es una forma de desacoplar la lógica empresarial independiente.

Por ejemplo, es posible que tenga un código como éste:

public Currency computeTotal(List<Product> products) { 
    Currency beforeTax = computeBeforeTax(products); 
    Currency afterTax = beforeTax.times(1.10); 
} 

Pero lo que si se quería extender este código para una nueva jurisdicción, con un esquema de impuesto sobre las ventas diferente? Se puede inyectar la lógica para calcular el impuesto, como este:

public interface TaxScheme { 
    public Currency applyTax(Currency beforeTax); 
} 

public class TenPercentTax implements TaxScheme { 
    public Currency applyTax(Currency beforeTax) { 
     return beforeTax.times(1.10); 
    } 
} 

public Currency computeTotal(List<Product> products, TaxScheme taxScheme) { 
    Currency beforeTax = computeBeforeTax(products); 
    Currency afterTax = taxScheme.applyTax(beforeTax); 
    return afterTax; 
} 
2

inversión de control significa que un alambres marco de tiempo de ejecución de todos los componentes juntos (por ejemplo primavera). La inyección de dependencia es una forma de IoC (no sé si existe otra forma de IoC) (ver: http://en.wikipedia.org/wiki/Inversion_of_control).

El patrón de estrategia es un patrón de diseño (definido por el GoF) donde el algoritmo puede ser reemplazado por otro (vea: http://en.wikipedia.org/wiki/Strategy_pattern). Esto está archivado por varias implementaciones de una misma interfaz. Al usar un IoC como Spring, si tiene varias implementaciones de una interfaz y si puede cambiar de una implementación a otra mediante la configuración, está utilizando el patrón de estrategia.

Cuestiones relacionadas