2010-11-14 14 views

Respuesta

84

DI y Strategy funcionan de la misma manera, pero Strategy se usa para dependencias más finas y de vida corta.

Cuando un objeto se configura con una Estrategia "fija", por ejemplo, cuando se construye el objeto, la distinción entre Estrategia y DI se difumina. Pero en un escenario DI es más inusual que las dependencias de los objetos cambien durante sus vidas, mientras que esto no es poco común con Strategy.

Además, puede pasar estrategias como argumentos a los métodos, mientras que el concepto relacionado de inyección de argumento de método no es generalizado y se usa principalmente en el contexto de pruebas automatizadas solamente.

La estrategia se centra en la intención y lo alienta a crear una interfaz con diferentes implementaciones que obedezcan el mismo contrato de comportamiento. DI se trata más que nada de tener una implementación de algún comportamiento y proporcionarlo.

Con DI puede descomponer su programa por otras razones además de poder intercambiar partes de la implementación. Una interfaz utilizada en DI con una sola implementación es muy común. Una "Estrategia" con una sola implementación concreta (nunca) no es un problema real, pero probablemente esté más cerca de la DI.

+0

Una interfaz utilizada en DI con una sola implementación es muy común, entonces, ¿qué es DI en este ¿caso particular? –

+1

Esta cita básicamente lo explica todo: 'en un escenario DI es más inusual que las dependencias de los objetos cambien durante sus vidas, mientras que esto no es raro con Strategy ' –

+0

Estrategia: Las clases están diseñadas para que se puedan configurar con un algoritmo en tiempo de ejecución.DI: Dichas clases obtienen un algoritmo (un objeto de Estrategia) inyectado en tiempo de ejecución. De la Memoria de patrones de diseño de GoF en http://w3sdesign.com. – GFranke

27

Puede usar DI como un patrón de estrategia, para que pueda intercambiar el algoritmo que se necesita para cada cliente, pero DI puede ir más allá ya que es una manera de desacoplar las partes de una aplicación, lo que no haría ser parte del patrón de estrategia.

Sería arriesgado decir que DI es solo un patrón de estrategia renombrado, ya que eso comienza a diluir para qué es realmente el patrón de estrategia, IMO.

+2

Creo que entiendo su esencia, pero no puedo expresarla correctamente ... Por lo tanto, usted dice DI es más un patrón de implementación mientras que la estrategia es más un patrón de diseño, y una forma de implementar estrategia es DI? –

+0

Eso suena como una buena manera de decirlo. DI es más que solo un patrón de estrategia. Encontré la misma confusión con AOP, donde la gente piensa que es un patrón de fábrica. Creo que DI puede implementar el patrón de estrategia, por lo que su nueva redacción parece ser fantástica. :) –

+0

esto puede ayudar con una redacción muy bella http://stackoverflow.com/a/4176811/22858 –

7

Las estrategias son elementos de nivel superior que se utilizan para cambiar la forma en que se calculan las cosas. Con la inyección de dependencia, puede cambiar no solo cómo se calculan las cosas, sino también cambiar lo que está allí.

Para mí, se hace evidente al usar pruebas unitarias. Para la ejecución del código de producción, tiene todos los datos ocultos (es decir, privados o protegidos); mientras que, con pruebas unitarias, la mayoría de los datos son públicos, así que puedo verlos con los Asserts.


ejemplo de la estrategia:

public class Cosine { 
    private CalcStrategy strat; 

    // Constructor - strategy passed in as a type of DI 
    public Cosine(CalcStrategy s) { 
    strat = s; 
    } 
} 

public abstract class CalcStrategy { 
    public double goFigure(double angle); 
} 

public class RadianStrategy extends CalcStrategy { 
    public double goFigure(double angle) { 
    return (...); 
    } 
} 
public class DegreeStrategy extends CalcStrategy { 
    public double goFigure(double angle) { 
    return (...); 
    } 
} 

en cuenta que no hay datos públicos que es diferente entre las estrategias. Tampoco hay ningún método diferente. Ambas estrategias comparten todas las mismas funciones y firmas.


Ahora para la inyección de dependencias:

public class Cosine { 
    private Calc strat; 

    // Constructor - Dependency Injection. 
    public Cosine(Calc s) { 
    strat = s; 
    } 
} 

public class Calc { 
    private int numPasses = 0; 
    private double total = 0; 
    private double intermediate = 0; 

    public double goFigure(double angle) { 
    return(...); 
} 

public class CalcTestDouble extends Calc { 
    // NOTICE THE PUBLIC DATA. 
    public int numPasses = 0; 
    public double total = 0; 
    public double intermediate = 0; 
    public double goFigure(double angle) { 
    return (...); 
    } 
} 

Uso:

public CosineTest { 

    @Test 
    public void testGoFigure() { 
    // Setup 
    CalcTestDouble calc = new CalcTestDouble(); 
    Cosine instance = new Cosine(calc); 

    // Exercise 
    double actualAnswer = instance.goFigure(0.0); 

    // Verify 
    double tolerance = ...; 
    double expectedAnswer = ...; 
    assertEquals("GoFigure didn't work!", expectedAnswer, 
     actualAnswer, tolerance); 

    int expectedNumPasses = ...; 
    assertEquals("GoFigure had wrong number passes!", 
     expectedNumPasses, calc.numPasses); 

    double expectedIntermediate = ...; 
    assertEquals("GoFigure had wrong intermediate values!", 
     expectedIntermediate, calc.intermediate, tolerance); 
    } 
} 

Aviso los últimos 2 cheques. Usaron los datos públicos en el doble de prueba que se inyectó en la clase bajo prueba. No pude hacer esto con el código de producción debido al principio de ocultamiento de los datos . No quería tener un código de prueba de propósito especial insertado en el código de producción. Los datos públicos tenían que estar en una clase diferente.

Se inyectó la prueba doble. Eso es diferente a solo una estrategia ya que afectó a datos y no solo a funciones.

11

Amigo, la inyección de dependencia es un patrón más general, y se trata de la dependencia de las abstracciones no concreciones y es una parte de cada patrón, pero el patrón de estrategia es una solución a más específica problema

esta es la definición de Wikipedia :

DI:

inyección de dependencias (DI) en programación orientada a objetos ordenador es un patrón de diseño con un núcleo principio de la SEP comportamiento de arating de resolución de dependencia. En otras palabras: una técnica para desacoplar altamente componentes de software dependientes.

patrón de estrategia:

En la programación informática, la estrategia patrón (también conocido como el patrón de política ) es un software patrón de diseño particular, con lo cual algoritmos pueden pueden seleccionar en tiempo de ejecución.

El patrón de estrategia está destinada a proporcionar un medio para definir una familia de algoritmos , encapsular cada uno como un objeto , y hacerlas intercambiables. El patrón de estrategia permite que los algoritmos varíen independientemente de los clientes que los utilizan.

33

La diferencia es lo que están tratando de lograr. El patrón de Estrategia se usa en situaciones en las que sabe que desea intercambiar implementaciones. Como ejemplo, es posible que desee formatear datos de diferentes maneras: puede usar el patrón de estrategia para intercambiar un formateador XML o un formateador CSV, etc.

Dependency Injection es diferente ya que el usuario no está intentando cambiar el comportamiento en tiempo de ejecución. Siguiendo el ejemplo anterior, podríamos estar creando un programa de exportación XML que utiliza un formateador XML. En lugar de estructurar el código como el siguiente:

public class DataExporter() { 
    XMLFormatter formatter = new XMLFormatter(); 
} 

le 'inyecta' el formateador en el constructor:

public class DataExporter { 
    IFormatter formatter = null; 

    public DataExporter(IDataFormatter dataFormatter) { 
    this.formatter = dataFormatter; 
    } 
} 

DataExporter exporter = new DataExporter(new XMLFormatter()); 

Hay algunas justificaciones para la inyección de dependencias, pero la principal es para la prueba. Es posible que tenga un caso en el que tenga un motor de persistencia de algún tipo (como una base de datos). Sin embargo, puede ser una molestia utilizar una base de datos real cuando ejecuta pruebas repetidamente. Entonces, para sus casos de prueba, usted inyectaría una base de datos ficticia, para que no incurra en esa sobrecarga.

Usando este ejemplo, puede ver la diferencia: siempre planeamos usar una estrategia de almacenamiento de datos, y es a la que le pasamos (la instancia de DB real).Sin embargo, en desarrollo y prueba, queremos utilizar diferentes dependencias, por lo que inyectamos diferentes concreciones.

3

La inyección de dependencia es un refinamiento del patrón de estrategia que explicaré brevemente. A menudo es necesario elegir entre varios módulos alternativos en tiempo de ejecución. Todos estos módulos implementan una interfaz común para que puedan usarse indistintamente. El propósito del patrón de estrategia es eliminar la carga de decidir sobre cuál de los módulos usar (es decir, qué "estrategia concreta" o dependencia) encapsulando el proceso de toma de decisiones en un objeto separado que llamaré el objeto de estrategia.

La inyección de dependencia refina el patrón de estrategia no solo al decidir qué estrategia concreta utilizar sino al crear una instancia de la estrategia concreta y "inyectarla" nuevamente al módulo de llamada. Esto es útil incluso si solo hay una única dependencia, ya que el conocimiento de cómo gestionar (inicializar, etc.) la instancia de estrategia concreta también puede ocultarse dentro del objeto de estrategia.

2

En realidad, la inyección de dependencia también se ve muy similar al patrón de puente. Para mí (y de acuerdo con la definición), el patrón Bridge es para acomodar diferentes versiones de de la implementación, mientras que el patrón de Estrategia es para una lógica totalmente diferente. Pero el código de muestra parece que está usando DI. Entonces, ¿tal vez DI es solo una técnica o implementación?

1

La estrategia es un campo para utilizar sus habilidades de inyección de dependencia. formas reales para poner en práctica la inyección de dependencias son las siguientes: -

  1. Eventos
  2. Los archivos de configuración de mapa de la unidad/estructura (o mediante programación), etc.
  3. métodos de extensión patrón
  4. Abstract Factory
  5. Inversion del patrón de control (utilizado tanto por la estrategia como por Abstract Factory)

Hay una cosa aunque eso hace que la estrategia se aparte. Como sabe en Unity cuando se inicia la aplicación, todas las dependencias están configuradas y no podemos cambiarlo más. Pero la estrategia admite cambios en la dependencia del tiempo de ejecución. ¡Pero NOSOTROS tenemos que administrar/inyectar la dependencia, no la responsabilidad de la Estrategia!

En realidad, la estrategia no habla de la inyección de dependencia. Si es necesario, se puede hacer a través de Abstract Factory dentro de un patrón de Estrategia. La estrategia solo habla de crear una familia de clases con interfaz y 'jugar' con ella. Mientras jugamos, si encontramos que las clases están en un nivel diferente, entonces tenemos que inyectarlo nosotros mismos, pero no el trabajo de Strategy.

Cuestiones relacionadas