9

I am trying to figure out when to use the DIC/IoC registry for configuring my software and when to use factories, along with the reasoning behind either approach.


I am using StructureMap as my DI container (DIC), which is easy to configure using registries. In the DIC practically all registered objects are static in the sense, that I do not need to change/exchange any implementation/instance at runtime, once the DIC is configured and they are configured in the DIC as singletons. However, since my software (SW) will run on different devices I do need to select a device-specific registry depending on the device that my SW runs on in order to configure the hardware accordingly.

Since the construction of some my objects requires reading in configuration files, I am using factories to return these instances to the DIC, in order to separate the reading of the configuration from the creation of the object. I registered the factory getters in the DIC for the corresponding plugin types.

Now say I have a plugin type IMotor with concrete types Motor1 and Motor2, which should be handled by a factory. There are now two ways I can decide how to configure my device:

  1. I pass information about the device that the SW is running on to a MotorFactory and it returns the correct motor, either Motor1 or Motor2. In this case the logic for deciding is inside the Factory.
  2. I configure the DIC according to the device it is running on and create two factories Motor1Factory and Motor2Factory, where one creates Motor1 and the other Motor2. In this case I would have differing registry entries for IMotor in the device-specific registries which use either Motor1Factory or Motor2Factory.

Now my question is: Which one of these two methods are preferable and why? To me, it seems the first case is not straight forward and a convoluted, since I am spreading out the logic that decides what type to instantiate throughout the code-base. Whereas in the second case I am effectively multiplying the number of factories in my code, since I will need a factory for (almost) each concrete type. It becomes even more confusing to me, when abstract factories are added to the mix.

So again: When should I use one method or the other? And more importantly: What are good indicators for deciding which way to go?

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
packoman
  • 291
  • 2
  • 5

3 Answers3

2

If you use both I will go for something simple :

  • DI/IoC : for every configuration that won't changed at runtime.
  • Factory : for creating instance of objects at runtime which depends of runtime input parameters. The instances of the factory are injected by the DI container.
Walfrat
  • 3,456
  • 13
  • 26
1

Abstract factories are used when you have objects related through a hierarchy that needs to vary together. I don't see that here.

What I see is that you are wondering if a factory should choose the motor or if the DIC should choose a factory that produces a particular motor.

It's hard to choose precisely because a factory and a DIC do very similar things. The difference is the factory is focused on a particular issue and the DIC is more general.

It comes down to this question: do you have a need for code that is particular to this issue that will live in the factory? Or is it more general like reading configuration details from a file?

Keep in mind that while you may only be choosing between Motor1 and Motor2 today, tomorrow there may be a Motor3. Favour the design that would make Motor3 easy to add.

Laiv
  • 14,283
  • 1
  • 31
  • 69
candied_orange
  • 102,279
  • 24
  • 197
  • 315
0

I would seperate the logic "which motor to use" into a special Factory called Builder (pattern) and use the IOC-Container for both motors as implementaton detail of the builder.

As a general rule:

  • you need a factory (or a builder) if you have to create many dynamic objects of the class/interface. (i.e. for every car you produce you have to create one new motor)
  • if you need only one static instance of a class the ioc/di can do the job for you (i.e you need only one static instance of the paymentservice and one static instance of the MotorBuilderService)
k3b
  • 7,488
  • 1
  • 18
  • 31