31

Any place where you need a run-time value to construct a particular dependency, Abstract Factory is the solution.

My qestion is: Why do many sources favor FactoryInterface over FactoryDelegate to implement this pattern? What are the pros and contras for both solutions?

Here is an example to understand what i mean

If you have a Service that needs a Repository with a certain Context then the Service constructor needs a factory to create or access its repository.

The common solution for this is to create a RepositoryFactoryInterface like this.

public IRepositoryFactory {
    IRepository Create(ContextInformation context);
}

public class MyService {
    private IRepositoryFactory repositoryFactory;
    public MyService(IRepositoryFactory repositoryFactory)
    {
        this.repositoryFactory = repositoryFactory:
    }

    public void DoSomeService()
    {
        ContextInformation context = ....;

        IRepository repository = this.repositoryFactory.Create(context);

        repository.Load(...);
        ...
        repository.Save(...);
    }
}

You also need to implement IRepositoryFactory interface some way

public MyEf4RepositoryFactory : IRepositoryFactory
{
    IRepository Create(ContextInformation context)
    {
        return new MyEf4Repository(context);
    }
}

... and use it in the application

public void main()
{
    IRepositoryFactory repoFactory = new MyEf4RepositoryFactory();
    IService service = new MyService(repoFactory); 

    service.DoSomeService();
}

----- End of mainstream solution ------

Instead of the RepositoryFactoryInterface you can do the same with a factorydelegate that requires less coding like this.

public class MyService {
    private Func<ContextInformation, IRepository> repositoryFactory;
    public MyService(Func<ContextInformation, IRepository> repositoryFactory)
    {
        this.repositoryFactory = repositoryFactory:
    }

    public void DoSomeService()
    {
        ContextInformation context = ....;

        IRepository repository = this.repositoryFactory(context);

        repository.Load(...);
        ...
        repository.Save(...);
    }
}

... and use it in the application

public void main()
{
    IService service = new MyService(context => new MyEf4Repository(context)); 

    service.DoSomeService();
}

In my opinion the factorydelegate context => new MyEf4Repository(context) is much more compact than declaring and implementing an interface IRepositoryFactory and MyEf4RepositoryFactory.

There must be a reason for this and i want to know why.

Here is one example source that uses the interface aproach: answer to is-there-a-pattern-for-initializing-objects-created-via-a-di-container

[Update]15 Months after asking this question and having more experience with the java universers i changed my mind: Now I prefer interfaces over delegates . But i cannot say why. It is just a feeling. Maybe because I am more used to it?

Community
  • 1
  • 1
k3b
  • 14,517
  • 7
  • 53
  • 85
  • 2
    The FactoryDelegate approach is the Functional way of doing things. – George Nov 16 '14 at 19:36
  • 1
    Here's my discussion on the topic. I think the main time interfaces are better is when there is a generic type argument on the method but not the interface. https://christianfindlay.com/2020/05/15/c-delegates-with-ioc-containers-and-dependency-injection/ – Christian Findlay May 16 '20 at 04:21

5 Answers5

13

Any place where you need a run-time value to construct a particular dependency, Abstract Factory is the solution.

I would argue against this. Dependencies should not be constructed using runtime data, as explained here. In summary the article states:

Don't inject runtime data into application components during construction; it causes ambiguity, complicates the composition root with an extra responsibility and makes it extraordinarily hard to verify the correctness of your DI configuration. Instead, let runtime data flow through the method calls of constructed object graphs.

When we let runtime data "flow through the method calls of constructed object graphs" instead, you'll see the usefulness of Abstract Factories decline. They might still be used when runtime data is used to choose from multiple dependencies (compared to injecting runtime data into a dependency), but even then Abstract Factories are typically not the best solution, as explained here. In summary the article states:

Generally, the use of a factory abstraction is not a design that considers its consumers. According to the Dependency Injection Principle (DIP), abstractions should be defined by their clients, and since a factory increases the number of dependencies a client is forced to depend upon, the abstraction is clearly not created in favor of the client and we can therefore consider this to be in violation of the DIP.

Instead, patterns such as Facade, Composite, Mediator and Proxy are generally a better solution.

That doesn't mean you can't have code in your application that produces dependencies, but it should not be defined as abstraction that is used by other application components. Instead, factory-like behavior should be encapsulated into adapters that are defined as part of your Composition Root.

When you only have these factory-like logic and dependencies as part of your Composition Root, it doesn't really matter whether you define an IRepositoryFactory or merely use an Func<IRepository> to construct such dependency, since the IRepositoryFactory would be defined in the Composition Root as well (since the application has no business in using such factory).

That said, in the rare case that an Abstract Factory is the right abstraction (which will typically happen when you are building a reusable framework), I do find the use of factory interfaces much more intend revealing than the use of delegates. It is a bit more verbose, but much clearer what the meaning is of such a thing. An IControllerFactory is more intend revealing than Func<IController>.

I would say this even more holds for factories that do not produce dependencies but data values instead. Take for instance the example of injecting a Func<DateTime> into a constructor. What does this actually mean and what value does it return? Is it intuitive that it returns a DateTime.Now, or does it return DateTime.Today, or something else? In that case it would be much clearer to define an ITimeProvider interface with a GetCurrentTime() method.

NOTE: This answer was updated on July 2017 to reflect my latest views.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • Func is indeed cryptic. But I find Func to be rather unambiguous. Maybe for the first case you should still create full factories, but for the other cases just use Func<...>? – dvdvorle Mar 23 '11 at 12:05
  • @Mr Happy: I just rather be a bit more verbose, but I think we will not agree about this :-) – Steven Mar 23 '11 at 13:46
  • 3
    Another point of happy middle ground - you can define custom delegate types (primarily for the benefit of a descriptive name) in many circumstances. – Nicholas Blumhardt Mar 25 '11 at 10:17
  • @Nicholas: Custom delegates. That's a nice one. I didn't think of that. It has still one downside though, and that is that `repositoryFactory()` is still less clear than `repositoryFactory.CreateNew()`. – Steven Mar 29 '11 at 09:53
4

I believe calling "factory" a delegate shouldn't be correct.

Factory has the responsability of instantiating some supported type, like some repository implementation.

Doing with delegates doesn't make sense because you're defining how your repository is instantiated whenever you want to create an instance of your service.

The question for me is why you should use a delegate if you can implement a generic parameter TRepository having "new" and "class" constraints, and, in construction time, instantiate the repository inside your service?

It's just an opinion, but it seems you want a shortcut instead of a better, well designed and optimal solution.

Summarizing:

  • Factory over a delegate allows inversion of control even for the factory itself.

  • Delegate over factory has zero advantage since you can even eliminate the need of a delegate itself - maybe, then, it's useless or redundant -.

  • Delegate "factory" won't be a factory because N ways of creating an instance of respository will be implemented, breaking the need and advantage of factory.

  • There's no need of manually create instances of some repository in the consumer's code. Just use a generic parameter so repository type can be provided in order to create an appropiate instance, thanks to inversion of control.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
4

Personally, I have always used the mainstream solution, simply because I didn't think of using a delegate.

After I thought of it, I faced the problem of separation of concerns. I'm using Ninject, and I didn't want my binding module to look like this (imagine the repositoy having some dependencies of itself):

class IoCModule : NinjectModule
{
    public override Load()
    {
        Bind<Func<Context, IRepository>>()
            .ToConstant( context => new MyEf4Repository(context, Kernel.Get<IRepositoryDependency1>, Kernel.Get<IRepositoryDependency2>) );
    }
}

That isn't readable at all. So I still used fully typed out abstract factories for Separation of Concern and readability.

Now I use the FuncModule described in this question (a la AutoFac). So I can do this:

class IoCModule : NinjectModule
{
    public override Load()
    {
        Bind<IRepository>().To<MyEf4Repository>();
        Bind<IRepositoryDependency1>().To<...>();
        Bind<IRepositoryDependency2>().To<...>();
    }
}

and let ninject figure the dependencies out for me. As you can see, it's both more readable than using the method described above, and having to bind the factories for each dependency. This is the way I made the transition from the mainstream solution to the delegate solution.

So to answer your question. The reason I used the mainstream solution was because I didn't know how to do it another way at first (this is partly caused by most blogs fully typing out the abstract factories, can you see the circle?).

Community
  • 1
  • 1
dvdvorle
  • 941
  • 1
  • 10
  • 25
3

I like and use the delegate solution as it is more concise. To avoid the readability problem with IoC containers that Mr. Happy mentioned, don't use Func. Instead create your own named delegate.

delegate IRepository RepositoryFactory(ContextInformation context);

Now you have the best of both worlds: the conciseness of delegates and the readability for IoC containers.

enl8enmentnow
  • 933
  • 7
  • 14
  • +1 for a simple compromise to get inted revealing back by becoming more verbose. what about naming the delegate `RepositoryDelegate` instead of `IRepository`. Otherwhise i would think it is an interface parameter. – k3b Aug 14 '12 at 03:31
  • 1
    IRespository is the return value of the function, and it is an interface as you guessed. The delegate is named RespositoryFactory, as it is also a factory and more meaningful than RepositoryDelegate. – enl8enmentnow Jun 26 '13 at 16:59
1

The whole point of using abstract factory over a simple factory is to group together individual factories.

In your case if you ever needed your delegate to produce anything other than an IRepository you would be in trouble..

Richard Friend
  • 15,800
  • 1
  • 42
  • 60
  • If you don't have a need to group together individual factories, but just want to supply runtime parameters to your dependencies, then _group together individual factories_ is just not what you want, and thus not the whole point of using abstract factory. Maybe in this context we're using the term "Abstract Factory" wrong? – dvdvorle Mar 23 '11 at 11:50
  • @MrHappy he said the point of using _abstract factory over a simple factory_. This is important as a simple factory doesn't necessarily have a relationship to other factories, whereas an _abstract_ factory does, as it is a base for a classification of factories. – rossipedia Aug 13 '12 at 22:20