Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using factories to create multiple objects when using Dependency Injection

I am trying to figure out how to create multiple objects when using Dependency Injection. As far as I understand the standard approach is to inject a Factory which is then used to create the objects. The part I struggle with is how the Factory creates the objects. So far I see two possible solutions:

The Factory just uses new() to create the object.

  • Isn't DI supposed to free me of the use of new for non value objects?
  • What happens if the Object to be created has dependencies that could be resolved by the IoC?

Use the Container as Serviclocator

  • solves the problems of just newing objects at the cost of introducing an antipattern or is it no longer an antipattern if the use of the serviclocater is constraind within the factories?

It feels like i can coose between a bad and a bad solution. Is there something I am missing or do I understand somthing wrong here?

Edit Currently I am not using an Ioc at all but thinking about Ninject. Although the Autofac DelegateFactories sound very promising.

like image 528
Thomas Avatar asked Jun 08 '11 09:06

Thomas


People also ask

Does dependency injection use factory pattern?

Factory pattern can be called as a tool to implement DI. Dependency injection can be implemented in many ways like DI using constructors, using mapping xml files etc. That's true that Factory Pattern is one of the way implementing Dependency Injection.

What type of design pattern is dependency injection?

In software engineering, dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. A form of inversion of control, dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs.


2 Answers

For starters, I don't consider using a container as service locator in factories an anti-pattern. There are genuine circumstances where it is entirely appropriate. Come to think about it, container aware factories are really container extensions, and those seem to be excluded from service locator bashing. Even the most pure IoC frameworks like AutoFac or Ninject have extensive extension capabilities. A most typical use case for this pattern is resolving to different implementations based on where the service is used.

With regards to using new to create instances inside factories, that is acceptable as well. The IoC/DI message got a bit distorted there and never using new is really a side effect, rather than the goal of DI. The first imperative of Dependency Injection is to externalise creation of dependencies from the component. A factory satisfies that imperative as long as it itself gets injected into component. The questions you need to ask yourself when evaluating such scenarios are:

  1. Does the component itself create its dependencies? A: No, the factory does.
  2. Can you make the component work with different dependencies without modifying it? A: Yes, by injecting a different factory.

I said this before, IoC containers are just factories on steroids. For 80% use case they work out of the box. The other 20% might require tweaks of the above two varieties. I tend to use container aware factories when I want to create components that require both registered dependencies and some input at run-time and new-ing factories when I create Domain objects that don't have dependencies on other services, but take all their construction parameters at run time.

like image 182
Igor Zevaka Avatar answered Sep 29 '22 05:09

Igor Zevaka


Although the interface for your factory will be defined at the application level, you would typically define the implementation of that factory class close to your DI configuration, thus as part of your composition root. Although calling the container directly from your code is an implementation of the Service Locator anti-pattern, any code that is defined inside the compostion root is merely mechanics and is therefore not Service Locator. As long as newing up objects or calling into the container is done inside (or very close to) the composition root, this is not a problem, because the application will still be clean from any locator / container.

In other words: use the factory approach. Whether or not you need to new up objects directly inside your factory or make use of the container, depends on the objects. Letting the container create the objects is preferable, especially when they got dependencies on their own, but not all objects can be created by the container. In that case you need to revert to the new operation. Both are fine when the code is part of the composition root and not of the application. The factory itself can have dependencies of its own. This should not be a problem. You can let the container wire-up the factory instance.

like image 42
Steven Avatar answered Sep 29 '22 06:09

Steven