Inyección de dependencia frente a patrón de fábrica

La mayoría de los ejemplos citados para el uso de Dependency Injection, podemos resolverlo también utilizando el patrón de fábrica. Parece que cuando se trata de uso / diseño, la diferencia entre la dependency injection y la fábrica es borrosa o delgada.

Una vez que alguien me dijo que es la forma en que lo usas, ¡eso hace la diferencia!

Una vez usé StructureMap un contenedor DI para resolver un problema, más tarde lo rediseñé para trabajar con una fábrica simple y eliminé las referencias a StructureMap.

¿Alguien puede decirme cuál es la diferencia entre ellos y dónde usar qué, cuál es la mejor práctica aquí?

Cuando se usa una fábrica, su código sigue siendo realmente responsable de crear objetos. Por DI subcontratas esa responsabilidad a otra clase o un marco, que está separado de tu código.

Sugeriría mantener los conceptos claros y simples. La Inyección de Dependencia es más un patrón arquitectónico para acoplar libremente componentes de software. El patrón de fábrica es solo una forma de separar la responsabilidad de crear objetos de otras clases con otra entidad. El patrón de fábrica se puede llamar como una herramienta para implementar DI. La dependency injections se puede implementar de muchas maneras, como DI usando constructores, usando mapas de archivos XML, etc.

Inyección de dependencia

En lugar de crear instancias de las partes, un automóvil pide las piezas que necesita para funcionar.

 class Car { private Engine; private SteeringWheel; private Tires tires; public Car(Engine engine, SteeringWheel wheel, Tires tires) { this.Engine = engine; this.SteeringWheel = wheel; this.Tires = tires; } } 

Fábrica

Pone las piezas juntas para hacer un objeto completo y esconde el tipo concreto de la persona que llama.

 static class CarFactory { public ICar BuildCar() { Engine engine = new Engine(); SteeringWheel steeringWheel = new SteeringWheel(); Tires tires = new Tires(); ICar car = new RaceCar(engine, steeringWheel, tires); return car; } } 

Resultado

Como puede ver, Factories y DI se complementan entre sí.

 static void Main() { ICar car = CarFactory.BuildCar(); // use car } 

¿Recuerdas los goldilocks y los tres osos? Bueno, la dependency injection es algo así. Aquí hay tres maneras de hacer lo mismo.

 void RaceCar() // example #1 { ICar car = CarFactory.BuildCar(); car.Race(); } void RaceCar(ICarFactory carFactory) // example #2 { ICar car = carFactory.BuildCar(); car.Race(); } void RaceCar(ICar car) // example #3 { car.Race(); } 

Ejemplo n. ° 1 : este es el peor porque oculta por completo la dependencia. Si miraras el método como una caja negra, no tendrías idea de que requería un automóvil.

Ejemplo n. ° 2 : Esto es un poco mejor porque ahora sabemos que necesitamos un automóvil ya que pasamos en una fábrica de automóviles. Pero esta vez estamos pasando demasiado, ya que todo lo que el método realmente necesita es un automóvil. Estamos pasando por una fábrica solo para construir el auto cuando el auto podría construirse fuera del método y pasar.

Ejemplo n. ° 3 : esto es ideal porque el método pide exactamente lo que necesita. No demasiado o muy poco. No tengo que escribir un MockCarFactory solo para crear MockCars, puedo pasar el simulacro directamente. Es directo y la interfaz no miente.

Este Google Tech Talk de Misko Hevery es sorprendente y es la base de lo que saqué de mi ejemplo. http://www.youtube.com/watch?v=XcT4yYu_TTs

Hay problemas que son fáciles de resolver con dependency injection que no se resuelven tan fácilmente con un conjunto de fábricas.

Algunas de las diferencias entre, por un lado, la inversión del control y la dependency injection (IOC / DI), y, por otro lado, un localizador de servicios o un conjunto de fábricas (fábrica), es:

IOC / DI es un ecosistema completo de objetos y servicios de dominio en sí mismo. Configura todo para ti en la forma que especifiques. Los objetos y servicios de su dominio son construidos por el contenedor y no se construyen por sí mismos: por lo tanto, no tienen ninguna dependencia en el contenedor ni en ninguna fábrica. IOC / DI permite un grado extremadamente alto de configurabilidad, con toda la configuración en un solo lugar (construcción del contenedor) en la capa superior de su aplicación (la GUI, la interfaz web).

Factory abstrae parte de la construcción de los objetos y servicios de su dominio. Pero los objetos de dominio y los servicios siguen siendo responsables de descubrir cómo construir ellos mismos y cómo obtener todas las cosas de las que dependen. Todas estas dependencias “activas” se filtran a través de todas las capas de su aplicación. No hay un solo lugar para configurar todo.

Una desventaja de DI es que no puede inicializar objetos con lógica. Por ejemplo, cuando necesito crear un personaje que tenga nombre y edad aleatorios, DI no es la opción sobre el patrón de fábrica. Con las fábricas, podemos encapsular fácilmente el algoritmo aleatorio a partir de la creación de objetos, que admite uno de los patrones de diseño llamado “Encapsular lo que varía”.

La administración del ciclo de vida es una de las responsabilidades que asumen los contenedores de dependencia, además de la creación de instancias e inyección. El hecho de que el contenedor a veces hace referencia a los componentes después de la instanciación es la razón por la que se llama un “contenedor” y no una fábrica. Los contenedores de dependency injection generalmente solo hacen referencia a los objetos que necesita para administrar ciclos de vida, o que se reutilizan para futuras inyecciones, como singletons o flyweights. Cuando se configura para crear nuevas instancias de algunos componentes para cada llamada al contenedor, el contenedor generalmente se olvida del objeto creado.

De: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html

El motivo por el cual Inyección de dependencia (DI) y Patrones de fábrica son similares es porque son dos implementaciones de Inversión de control (IoC) que es una architecture de software. En pocas palabras, son dos soluciones para el mismo problema.

Entonces, para responder a la pregunta, la principal diferencia entre el patrón Factory y DI es cómo se obtiene la referencia del objeto. Con la dependency injection como su nombre lo indica, la referencia se inyecta o se le da a su código. Con el patrón Factory, su código debe solicitar la referencia para que su código recupere el objeto. Ambas implementaciones eliminan o desacoplan el enlace entre el código y la clase o tipo subyacente de la referencia del objeto que utiliza el código.

Vale la pena señalar que los patrones Factory (o los patrones Abstract Factory que son fábricas que devuelven nuevas fábricas que devuelven referencias a objetos) se pueden escribir para elegir o vincular dinámicamente al tipo o clase de objeto que se solicita en tiempo de ejecución. Esto los hace muy similares (incluso más que DI) al patrón del localizador de servicios, que es otra implementación del IoC.

El patrón de diseño de fábrica es bastante antiguo (en términos de software) y ha existido por un tiempo. Dado que la popularidad reciente del patrón arquitectónico IoC está teniendo un resurgimiento.

Supongo que cuando se trata de patrones de diseño de IoC: los inyectores se inyectan, los localizadores se ubican y las fábricas se han refabricado.

Creo que DI es un tipo de capa de abstracción en las fábricas, pero también proporciona beneficios más allá de la abstracción. Una verdadera fábrica sabe cómo crear instancias de un solo tipo y configurarlo. Una buena capa DI proporciona la capacidad, a través de la configuración, de crear instancias y configurar muchos tipos.

Obviamente, para un proyecto con algunos tipos simples que requieren una lógica comercial relativamente estable en su construcción, el patrón de fábrica es simple de entender, implementar y funciona bien.

OTOH, si tiene un proyecto que contiene numerosos tipos cuyas implementaciones espera cambiar a menudo, DI le ofrece la flexibilidad a través de su configuración para hacerlo en tiempo de ejecución sin tener que recomstackr sus fábricas.

Sé que esta pregunta es antigua pero me gustaría agregar mis cinco centavos,

Creo que la dependency injection (DI) es en muchos aspectos como un patrón de fábrica (FP) configurable, y en ese sentido, cualquier cosa que pudieras hacer con DI, podrás hacerlo con dicha fábrica.

En realidad, si usa la spring, por ejemplo, tiene la opción de autover recursos (DI) o hacer algo como esto:

 MyBean mb = ctx.getBean("myBean"); 

Y luego usa esa instancia ‘mb’ para hacer cualquier cosa. ¿No es eso una llamada a una fábrica que te devolverá una instancia?

La única diferencia real que noto entre la mayoría de los ejemplos de FP es que puedes configurar lo que “myBean” está en un xml o en otra clase, y un framework funcionará como la fábrica, pero aparte de eso es lo mismo, y tú Puede tener ciertamente una fábrica que lea un archivo de configuración u obtenga la implementación que necesita.

Y si me pides mi opinión (y sé que no), creo que DI hace lo mismo pero agrega más complejidad al desarrollo, ¿por qué?

Bueno, para empezar, para que sepas cuál es la implementación que se usa para cualquier bean que conectes con DI, tienes que ir a la configuración misma.

pero … ¿qué pasa con la promesa de que no tendrás que saber la implementación del objeto que estás utilizando? pfft! ¿seriamente? cuando utilizas un enfoque como este … ¿no eres el mismo que escribe la implementación? e incluso si no lo hace, ¿no está casi todo el tiempo mirando cómo la implementación hace lo que se supone que debe hacer?

y por último, no importa cuánto le prometa un marco de DI que construirá cosas desacopladas de él, sin dependencias con sus clases, si está utilizando un marco, construya todo en él, si tiene que cambiar el enfoque o el marco no será una tarea fácil … ¡SIEMPRE! … pero, dado que construyes todo alrededor de ese marco particular en lugar de preocuparte por cuál es la mejor solución para tu negocio, entonces enfrentarás un problema biológico al hacer eso.

De hecho, la única aplicación empresarial real para un enfoque de FP o DI que puedo ver es si necesita cambiar las implementaciones que se utilizan en tiempo de ejecución , pero al menos los marcos que conozco no le permiten hacer eso, debe dejarlo. todo perfecto en la configuración en el momento del desarrollo y si necesita que use otro enfoque.

Entonces, si tengo una clase que se desempeña de manera diferente en dos ámbitos en la misma aplicación (digamos, dos compañías de una explotación) tengo que configurar el marco para crear dos beans diferentes y adaptar mi código para usar cada uno. ¿No es lo mismo que escribiría algo como esto?

 MyBean mb = MyBeanForEntreprise1(); //In the classes of the first enterprise MyBean mb = MyBeanForEntreprise2(); //In the classes of the second enterprise 

lo mismo que esto:

 @Autowired MyBean mbForEnterprise1; //In the classes of the first enterprise @Autowired MyBean mbForEnterprise2; //In the classes of the second enterprise 

Y esto:

 MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise1"); //In the classes of the first enterprise MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise2"); //In the classes of the second enterprise 

En cualquier caso, tendrá que cambiar algo en su aplicación, ya sean clases o archivos de configuración, pero tendrá que hacerlo y volver a implementarlo.

¿No sería bueno hacer algo así como esto?

 MyBean mb = (MyBean)MyFactory.get("mb"); 

Y de esa forma, ¿configura el código de la fábrica para obtener la implementación correcta en tiempo de ejecución según la empresa de usuario registrada? Ahora ESO sería útil. Simplemente podría agregar un nuevo jar con las nuevas clases y establecer las reglas tal vez incluso en tiempo de ejecución (o agregar un nuevo archivo de configuración si deja esta opción abierta), sin cambios en las clases existentes. ¡Esta sería una fábrica Dinámica!

¿No sería más útil que tener que escribir dos configuraciones para cada empresa, y tal vez incluso tener dos aplicaciones diferentes para cada uno?

Puede decirme que no necesito hacer el cambio en tiempo de ejecución, así que configuro la aplicación, y si heredo la clase o utilizo otra implementación, simplemente cambio la configuración y la redistribución. Ok, eso también se puede hacer con una fábrica. Y se honesto, ¿cuántas veces haces esto? tal vez solo cuando tienes una aplicación que va a usarse en otro lugar de tu empresa, y le pasas el código a otro equipo, y harán cosas como esta. Pero bueno, eso también se puede hacer con la fábrica, ¡y sería aún mejor con una fábrica dinámica!

De todos modos, la sección de comentarios si está abierta para que me mates.

Teoría

Hay dos puntos importantes a considerar:

  1. Quién crea objetos

    • [Factory]: debe escribir el objeto HOW que debe crearse. Tiene una clase Factory separada que contiene lógica de creación.
    • [Inyección de Dependencia]: en casos prácticos, se realizan mediante marcos externos (por ejemplo, en Java que sería spring / ejb / guice). La inyección ocurre “mágicamente” sin creación explícita de nuevos objetos
  2. Qué tipo de objetos maneja:

    • [Fábrica]: generalmente responsable de la creación de objetos con estado
    • [Inyecciones de dependencia] Es más probable que cree objetos sin estado

Ejemplo práctico de cómo usar la inyección de fábrica y de dependencia en un solo proyecto

  1. Lo que queremos construir

Módulo de aplicación para crear orden que contiene múltiples entradas llamadas orderline.

  1. Arquitectura

Supongamos que queremos crear la siguiente architecture de capa:

enter image description here

Los objetos de dominio pueden ser objetos almacenados dentro de la base de datos. Repository (DAO) ayuda con la recuperación de objetos de la base de datos. El servicio proporciona API a otros módulos. Alows para las operaciones en el módulo de order

  1. Capa de dominio y uso de fábricas

Las entidades que estarán en la base de datos son Order y OrderLine. El pedido puede tener múltiples OrderLines. Relación entre orden y línea de pedido

Ahora viene una parte importante del diseño. ¿Deberían los módulos externos a este crear y administrar OrderLines por sí mismos? No. Order Line debería existir solo cuando tiene Order asociado con él. Sería mejor si pudieras ocultar la implementación interna a clases externas.

¿Pero cómo crear Order sin conocimiento sobre OrderLines?

Fábrica

Alguien que quiera crear un pedido nuevo usó OrderFactory (que ocultará detalles sobre cómo creamos el pedido).

enter image description here

Así es como se verá dentro de IDE. Las clases fuera domain paquete de domain usarán OrderFactory lugar de constructor dentro de Order

  1. La inyección de Dependency Injection Dependency se usa más comúnmente con capas sin estado como el repository y el servicio.

OrderRepository y OrderService son gestionados por el marco de dependency injections. El repository es responsable de administrar las operaciones de CRUD en la base de datos. El servicio inyecta el repository y lo usa para guardar / encontrar clases de dominio correctas.

enter image description here

Con la dependency injection, el cliente no necesita obtener sus dependencias por sí mismo, todo está preparado de antemano.

Con las fábricas, alguien tiene que llamar a esos para llevar los objetos generados al lugar donde se necesitan.

La diferencia radica principalmente en esta única línea donde se realiza la llamada a la fábrica y la búsqueda del objeto construido.

Pero con las fábricas tienes que escribir esta 1 línea donde sea que necesites tal objeto. Con DI solo tienes que crear el cableado (relación entre el uso y el objeto creado) una vez y simplemente confiar en la presencia del objeto después en todas partes. Por otro lado, DI a menudo requiere un poco más (cuánto depende del marco) trabajar en el lado de la preparación.

COI es un concepto que se implementa de dos maneras. La creación de dependencias y la dependency injection, fábrica / fábrica abstracta son el ejemplo de creación de dependencia. Inyección de dependencia es constructor, setter e interfaz. El núcleo del COI es no depender de las clases concretas, sino definir el resumen de los métodos (por ejemplo, una interfaz / clase abstracta) y usar ese método abstracto para llamar de una clase concreta. Al igual que el patrón Factory, devuelve la clase base o la interfaz. De forma similar, la dependency injection utiliza la clase base / interfaz para establecer el valor de los objetos.

Tenía la misma pregunta tan pronto como leí sobre DI y terminé en esta publicación. Así que finalmente esto es lo que entendí, pero por favor corríjanme si estoy equivocado.

“Hace mucho tiempo hubo pequeños reinos con sus propios órganos de gobierno controlando y tomando decisiones basadas en sus propias reglas escritas. Más tarde se formó un gran gobierno eliminando todos estos pequeños cuerpos de gobierno que tienen un conjunto de reglas (constitución) y se implementan a través de los tribunales”

Los cuerpos gobernantes de los reinos pequeños son “fábricas”

El gran gobierno es el “Inyector de Dependencia”.

Puede ver este enlace para comparar los dos enfoques (y otros) en un ejemplo real.

Básicamente, cuando los requisitos cambian, terminas modificando más código si utilizas fábricas en lugar de DI.

Esto también es válido con DI manual (es decir, cuando no existe un marco externo que proporcione las dependencias a sus objetos, pero los pasa en cada constructor).

Creo que DI es una forma de configuración o creación de instancias de un bean. El DI se puede hacer de muchas maneras como constructor, setter-getter, etc.

El patrón de fábrica es solo otra forma de crear instancias de frijoles. este patrón se usará principalmente cuando tenga que crear objetos utilizando el patrón de diseño de fábrica, porque al usar este patrón no configura las propiedades de un bean, solo crea una instancia del objeto.

Mira este enlace: Inyección de dependencia

Binoj,

No creo que tengas que elegir una sobre la otra.

El acto de mover una clase o interfaz dependiente a un constructor o instalador de clase sigue el patrón DI. El objeto que pasa al constructor o conjunto puede implementarse con Factory.

¿Cuándo usar? Usa el patrón o los patrones que están en tu timonera de desarrollador. ¿Con qué se sienten más cómodos y encuentran más fácil de entender?

Mis pensamientos:

Inyección de dependencia: pasar colaboradores como parámetros a los constructores. Dependency Injection Framework: una fábrica genérica y configurable para crear los objetos para pasar como parámetros a los constructores.

Un Marco de Inyección es una implementación del Patrón de Fábrica.

Todo depende de tus requisitos. Si necesita implementar el patrón de fábrica en una aplicación, es muy probable que sus requisitos se cumplan con una de las innumerables implementaciones de marcos de inyección que existen.

Solo debe implementar su propia solución si ninguno de los marcos de terceros puede cumplir sus requisitos. Cuantos más códigos escribas, más código tienes que mantener. El código es un pasivo, no un activo.

Los argumentos sobre qué implementación debe usar no son tan importantes como la comprensión de las necesidades arquitectónicas de su aplicación.

Patrón de diseño de fábrica

El patrón de diseño de fábrica se caracteriza por

  • Una interfaz
  • Clases de implementación
  • Una fábrica

Puedes observar algunas cosas cuando te preguntas como sigue

  • ¿Cuándo creará la fábrica un objeto para las clases de implementación – tiempo de ejecución o tiempo de comstackción?
  • ¿Qué sucede si quiere cambiar la implementación en tiempo de ejecución? – No es posible

Estos son manejados por inyección de Dependencia.

Inyección de dependencia

Puede tener diferentes formas en que puede inyectar dependencia. Por simplicidad, vamos con la inyección de interfaz

En DI, el contenedor crea las instancias necesarias y las “inyecta” en el objeto.

Por lo tanto, elimina la instanciación estática.

Ejemplo:

 public class MyClass{ MyInterface find= null; //Constructor- During the object instantiation public MyClass(MyInterface myInterface ) { find = myInterface ; } public void myMethod(){ find.doSomething(); } } 

De un valor nominal se ven iguales

En términos muy simples, Factory Pattern, un patrón de creación nos ayuda a crear un objeto: “Definir una interfaz para crear un objeto”. Si tenemos un grupo de objetos de valor clave (por ejemplo, Diccionario), pasando la clave a la Fábrica (me refiero al Patrón de Fábrica Simple) puede resolver el Tipo. ¡Trabajo hecho! El Marco de Inyección de Dependencia (como el Mapa de Estructura, Ninject, Unity … etc) por otro lado parece estar haciendo lo mismo.

Pero … “No reinventar la rueda”

Desde una perspectiva arquitectónica es una capa vinculante y “No reinventar la rueda”.

Para una aplicación de grado empresarial, el concepto de DI es más una capa arquitectónica que define dependencias. Para simplificar esto aún más, puede pensar en esto como un proyecto de biblioteca de clases separado, que resuelve la dependencia. La aplicación principal depende de este proyecto en el que el solucionador de dependencias se refiere a otras implementaciones concretas y a la resolución de dependencias.

Además de “GetType / Create” de una fábrica, la mayoría de las veces necesitamos más características (capacidad de usar XML para definir dependencias, burlas y pruebas unitarias, etc.). Como mencionó el Mapa de estructura, mire la lista de características Mapa de estructura . Es claramente más que simplemente resolver el mapeo de objetos simple. ¡No reinventes la rueda!

Si todo lo que tienes es un martillo, todo parece un clavo

Dependiendo de tus requisitos y del tipo de aplicación que crees, debes tomar una decisión. Si tiene pocos proyectos (puede ser uno o dos …) e involucra pocas dependencias, puede elegir un enfoque más simple. Es como utilizar ADO .Net acceso a datos sobre el uso de Entity Framework para una simple llamada de base de datos 1 o 2, donde la introducción de EF es una exageración en ese escenario.

Pero para un proyecto más grande o si su proyecto se agranda, recomiendo encarecidamente tener una capa DI con un marco y dejar espacio para cambiar el marco DI que usa (Use una Fachada en la Aplicación Principal (Aplicación Web, Api Web, Escritorio) ..etc.).

Creo que 3 aspectos importantes rigen los objetos y su uso:
1. Instanciación (de una clase junto con la inicialización, si la hay).
2. Inyección (de la instancia así creada) donde se requiere.
3. Gestión del ciclo de vida (de la instancia así creada).

Utilizando el patrón Factory, se logra el primer aspecto (instanciación) pero los dos restantes son cuestionables. La clase que usa otras instancias debe codificar las fábricas (en lugar de crear instancias) lo que dificulta las habilidades de acoplamiento. Además, la administración del ciclo de vida de las instancias se convierte en un desafío en una aplicación grande donde una fábrica se usa en múltiples lugares (particularmente, si la fábrica no administra el ciclo de vida de la instancia que devuelve, se pone feo).

Usando un DI (de patrón IoC) por otro lado, los 3 se abstraen fuera del código (al contenedor DI) y el bean administrado no necesita nada sobre esta complejidad. Acoplamiento flojo , un objective arquitectónico muy importante se puede lograr tranquilamente cómodamente. Otro objective arquitectónico importante, la separación de preocupaciones se puede lograr mucho mejor que las fábricas.

Considerando que las fábricas pueden ser adecuadas para pequeñas aplicaciones, las grandes sería mejor elegir DI en las fábricas.

La mayoría de las respuestas aquí explican la diferencia conceptual y los detalles de implementación de ambos. Sin embargo, no pude encontrar una explicación sobre la diferencia en la aplicación, que IMO es la más importante y sobre la que se preguntó OP. Así que déjenme reabrir este tema …

Una vez que alguien me dijo que es la forma en que lo usas, ¡eso hace la diferencia!

Exactamente. En 90% de los casos, puede obtener referencias de objetos usando Factory o DI y generalmente termina con esto último. En otro 10% de casos, usar Factory es solo la forma correcta . Estos casos incluyen la obtención de objetos por variable en los parámetros de tiempo de ejecución. Me gusta esto:

 IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com", useCookies: false, connectionTimeout: 120); 

En este caso, no es posible obtener el client de DI (o al menos requiere alguna solución fea). Por lo tanto, como regla general para tomar decisiones: si se puede obtener una dependencia sin parámetros calculados en tiempo de ejecución, se prefiere DI, de lo contrario use Factory.

Con una fábrica puede agrupar las interfaces relacionadas, por lo que si los parámetros pasados ​​se pueden agrupar en una fábrica, entonces también es una buena solución para la constructor overinjection mire este código *):

 public AddressModelFactory(IAddressAttributeService addressAttributeService, IAddressAttributeParser addressAttributeParser, ILocalizationService localizationService, IStateProvinceService stateProvinceService, IAddressAttributeFormatter addressAttributeFormatter) { this._addressAttributeService = addressAttributeService; this._addressAttributeParser = addressAttributeParser; this._localizationService = localizationService; this._stateProvinceService = stateProvinceService; this._addressAttributeFormatter = addressAttributeFormatter; } 

Mira el constructor, solo tienes que pasar IAddressModelFactory allí, por lo que hay menos parámetros *):

  public CustomerController(IAddressModelFactory addressModelFactory, ICustomerModelFactory customerModelFactory, IAuthenticationService authenticationService, DateTimeSettings dateTimeSettings, TaxSettings taxSettings, ILocalizationService localizationService, IWorkContext workContext, IStoreContext storeContext, ICustomerService customerService, ICustomerAttributeParser customerAttributeParser, ICustomerAttributeService customerAttributeService, IGenericAttributeService genericAttributeService, ICustomerRegistrationService customerRegistrationService, ITaxService taxService, CustomerSettings customerSettings, AddressSettings addressSettings,... 

Usted ve en CustomerController una gran cantidad de parámetros pasados, sí puede ver esto como constructor overinjection pero así es como funciona DI. Y no hay nada malo con CustomerController .

*) El código es de nopCommerce.

En términos simples, el método de Inyección de Dependencia vs Fábrica implica un mecanismo de empuje contra extracción respectivamente.

Con el mecanismo de extracción: la clase indirectamente tiene dependencia en el Método de Fábrica que a su vez tiene dependencia en clases concretas.

Con el mecanismo Push: el componente raíz se puede configurar con todos los componentes dependientes en una sola ubicación y, de este modo, se promueve un alto mantenimiento y un acoplamiento flexible.

With Factory method responsibility still lies with class (though indirectly) to create new object where as with dependency injection that responsibility is outsourced (at the cost of leaking abstraction though)

I think these are orthogonal and can be used together. Let me show you an example I recently came across at work:

We were using the Spring framework in Java for DI. A singleton class ( Parent ) had to instantiate new objects of another class ( Child ), and those had complex collaborators:

 @Component class Parent { // ... @Autowired Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) { this.dep1 = dep1; this.dep2 = dep2; } void method(int p) { Child c = new Child(dep1, dep2, ..., depN, p); // ... } } 

In this example, Parent has to receive DepX instances only to pass them to the Child constructor. Problems with this:

  1. Parent has more knowledge of Child than it should
  2. Parent has more collaborators than it should
  3. Adding dependencies to Child involves changing Parent

This is when I realized a Factory would fit here perfectly:

  1. It hides all but the true parameters of the Child class, as seen by Parent
  2. It encapsulates the knowledge of creating a Child , which can be centralized in the DI configuration.

This is the simplified Parent class and the ChildFactory class:

 @Component class Parent { // ... @Autowired Parent(ChildFactory childFactory) { this.childFactory = childFactory; } void method(int p) { Child c = childFactory.newChild(p); // ... } } @Component class ChildFactory { // ... @Autowired Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) { this.dep1 = dep1; this.dep2 = dep2; // ... this.depN = depN; } Child newChild(int p) { return new Child(dep1, dep2, ..., depN, p); } } 

I use both to create an Inversion Of Control strategy with more readability for developers who need to maintain it after me.

I use a Factory to create my different Layer objects (Business, Data Access).

 ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness(); 

Another developer will see this and when creating an Business Layer object he looks in BusinessFactory and Intellisense gives the developer all the possible Business Layers to create. Doesn’t have to play the game, find the Interface I want to create.

This structure is already Inversion Of Control. I am no longer responsible for creating the specific object. But you still need to ensure Dependency Injection to be able to change things easily. Creating your own custom Dependency Injection is ridiculous, so I use Unity. Within the CreateCarBusiness() I ask Unity to Resolve which class belongs to this and it’s lifetime.

So my code Factory Dependency Injection structure is:

 public static class BusinessFactory { public static ICarBusiness CreateCarBusiness() { return Container.Resolve(); } } 

Now I have the benefit of both. My code is also more readable for other developers as towards scopes of my objects I use, instead of Constructor Dependency Injection which just says every object is available when the class is created.

I use this to change my Database Data Access to a custom coded Data Access layer when I create Unit Tests. I don’t want my Unit Tests to communicate with databases, webservers, e-mail servers etc. They need to test my Business Layer because that’s where the intelligence is.

Using dependency injection is much better in my opinion if you are: 1. deploying your code in small partition, because it handles well in decoupling of one big code. 2. testability is one of the case DI is ok to use because you can mock easily the non decoupled objects. with the use of interfaces you can easily mock and test each objects. 3. you can simultaneously revised each part of the program without needing to code the other part of it since its loosely decoupled.