3

I have a factory to build cars... it a basic factory, it accepts name of a car, looks for all classes that implement ICar, chooses the correct type based on car name and initializes the car using reflection.

public class CarFactory
{
    Dictionary<string, Type> cars;

    public ICar CreateInstance(string carName)
    {
        // choose type of class from all classes that implement ICar 
        Type t = GetTypeToCreate(carName); 
        return Activator.CreateInstance(t) as ICar;
    }

    // some more code...
}

Now, I have a service which uses CarFactory. What is the right way to initialize CarFactory in my service?

One solution would be to inject the factory, but Factory Pattern is a form of IoC itself and it feels odd to inject a factory. According to Nikola Malovic:

using factories together with IoC doesn’t make a lot of sense because IoC container is in a sense “universal abstract factory”.

In other words, in my experience any time I thought about adding a factory I ended with much simpler IoC based solution so that’s why I would dare to say that “IoC kill the Factory star"

The above makes total sense to me, though I have not been able to think of a solution to replace my Factory with DI.

So my question is (for those who use factory pattern) how should I initialize it?


To avoid making the question very long, I have used a simplified CarFactory example in this question. I have posted the complete example here.

Hooman Bahreini
  • 14,480
  • 11
  • 70
  • 137
  • 3
    The quote says that factories and DI containers do the same job, and you don't need both tools for one job. So the answer to your question is that there is no right way to initialize a factory. Don't use factories. Use a DI container. – jaco0646 Oct 29 '18 at 13:02
  • @jaco0646: thanks. If that's the case then injection of factory is ruled out... would it be fair to say that using a static factory is the way to go (as opposed in instantiating it in the constructor)? Just like a static DI container? – Hooman Bahreini Oct 29 '18 at 22:38
  • 1
    What do you mean by *'initialise?'* – Mark Seemann Oct 30 '18 at 20:57
  • @MarkSeemann: thanks, I mean should I use a static factory, instantiate the factory in the constructor of the Service or inject the factory? – Hooman Bahreini Oct 30 '18 at 20:59

3 Answers3

1

It is better to inject dependencies (constructor, property, method) into your types. And it is best to avoid creating dependencies using new-operator.

To make it even better you should define an interface for you CarFactory (ICarFactory) and change your service to depend on that type.

In tests you could mock ICarFactory and provide special implementations for your test cases.

Jehof
  • 34,674
  • 10
  • 123
  • 155
  • thanks a lot. Yes, I would use an ICarFactory for DI... so injection of a factory is a common practice? just wanted to make sure what I am doing is not a design smell or something like that? – Hooman Bahreini Oct 29 '18 at 07:15
  • 1
    @Hooman I often inject Factory-abstractions (IFactory) into my types. I think not that this is a design flaw or smell. – Jehof Oct 29 '18 at 07:19
  • You could also register your cars in the IOC-Container and use that behind a ICarFactory to provide you the required car instances. – Jehof Oct 29 '18 at 07:21
  • thanks again... I updated my question with some reference advising against injection of a factory... in fact against using factory pattern at the first place... I am beginning to think my question might be opinion based. – Hooman Bahreini Oct 29 '18 at 08:11
  • 2
    > I am beginning to think my question might be opinion based Thats true :-). I would say use that what best fits your solution, but always use interfaces and inject dependencies. – Jehof Oct 29 '18 at 08:14
1

I think it is wrong compare Dependency Injection containers and Factories.
Yes both responsibility is to create an instance of some type.

But DI container responsibility to instantiate an instance and all its dependencies based on DI configurations. Usually DI containers instantiate objects in entry point of application (main method or request in web applications).

Where Factory will create an instance of the type based on some business logic of your application or based on some values which can be accessed only during runtime.

Factory is normal class as others classes and it is ok to inject it as a dependency.

In your particular case you know name of the car only in runtime, so you will need some class which responsibility will be "convert" name to the instance of the car.

Fabio
  • 31,528
  • 4
  • 33
  • 72
1

As usual, with these kinds of questions, the answer is that It Depends™. It depends on the problem you're trying solve. While this question is tagged with both dependency-injection and inversion-of-control (to a degree the same idea) none of these are goals in themselves, but only a means to achieve a proper goal.

Usually, the goal is decoupling of behaviour. This leads to the first question, then:

Why does CreateInstance return ICar instances?

I assume here that ICar is an interface. Is ICar polymorphic? Do you have more than one implementation of that interface?

An object named car sounds to me like an Entity, and those should usually not be injected, since they typically represent data, and not behaviour.

For the sake of argument, though, let's assume that ICar is truly polymorphic.

As shown here, CarFactory looks deterministic. It's hard to tell, though, because not the entire implementation is shown. If, however, it's referentially transparent, then why does it even need to be initialised?

Couldn't it just be a static function?

public static class CarFactory
{
    public static ICar CreateInstance(string carName)
    {
        // choose type of class from all classes that implement ICar 
        Type t = GetTypeToCreate(carName); 

        return Activator.CreateInstance(t) as ICar;
    }

    // some more code...
}
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Thanks a lot. Yes ICar is polymorphic, and Car is my ViewModel. I tried to avoid a long post and therefore simplified my code. I updated the question with a link to the actual code [here](https://codereview.stackexchange.com/questions/206692/instantiating-object-using-a-static-factory) – Hooman Bahreini Oct 31 '18 at 21:30
  • In the answer above you are saying: "An object named car sounds to me like an Entity, and those should usually not be injected, since they typically represent data, and not behaviour." I have read your other answer which is linked but there you are explaining that Entities should not have dependency on other classes such as Repositories... please, are you able to explain why an entity such as `Car` should usually not be injected? – Hooman Bahreini Sep 25 '19 at 09:29
  • 1
    @HoomanBahreini An Entity such as `Car` typically represents domain data, and there'd often be thousands, if not millions, of `Car` objects available in your system. If you want to inject one, which one do you pick? – Mark Seemann Sep 25 '19 at 19:04