Andreas
Andreas

Reputation: 2366

Understanding the difference between using interface-based factories and normal IoC interfaces instansiation

First of, sorry if my use of terms are invalid, trying to get it right but not sure if it is, it's a little confusing for me right now.

I'm using Windsor and having trouble figuring out when and how (I think) to use interface-based factories instantiating and not always the normal ctor(IObj obj).

Let me give an example. I have this constructor

private ICache _cache;
private ICache _cache2;
public HomeController(ICacheFactory cacheFactory, ICache cache)
{
    this._cache = cacheFactory.Create<ICacheFactory>();
    this._cache2 = cache;
}

The way I have setup my code, _cache and _cache2 return the exakt same object. Why should I ever use the ICacheFactory way of instansiating a class?

This is how I've configured it

public interface ICacheFactory
{
    ICache Create<T>();
}

public interface ICache
{
    bool Get<T>(string key, out T exists);
}

public bool Get<T>(string key, out T result)
    {
        // my code
    }

public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());
        container.AddFacility<TypedFactoryFacility>();
        container.Register(Component.For<ICacheFactory>().AsFactory());

        container.Register(Component.For<ICache>().ImplementedBy<CacheFactory>().LifestyleTransient());
    }

I'm thinking CacheFactory as when I do

public class CacheFactory : ICache
{
    private static ICache cacheObject;
    public static ICache Current
    {
        get
        {
            if (cacheObject == null)
                cacheObject = new CacheFactory();

            return cacheObject;
        }
    }

    public bool Get<T>(string key, out T result)
    {
        // my code
    }
}

So am I complety way of in my way of thinking what the interface-based factories do and if not why should I ever use the ICacheFactory way of instansiating a class?

(I should be clear that I've read the Windsor documentation but not getting it 100%.)

Thanks for your time and I hope it's not to fuzzy.

Upvotes: 1

Views: 84

Answers (1)

Steven
Steven

Reputation: 172646

When applying dependency injection correctly, you'll find that this will dramatically reduce the amount of factories you need to use. Factories are still useful and sometimes needed, but their use is limited to the times that you either:

  1. Explicitly need to control the lifetime of the service (for instance because you need to dispose such instance at the end of the method)
  2. When you need to break the object graph by postponing the creation.

In most other cases, factories should not be used. Especially in the case that you are showing, where the factory is called inside the constructor. This is useless, because:

  1. You're not delaying the building of the object graph, since calling the factory from inside the constructor has the same effect as calling the factory just before calling the constructor.
  2. You are complicating your code base, since your HomeController now has a dependency on an extra abstraction ICacheFactory, while it could fulfill its needs with just the dependency on ICache alone. This also complicates testing. Why doe HomeController need to know about this factory at all?

Furthermore, you are stating that "_cache and _cache2 return the exact same object", so there's no need to inject two caches here. So your constructor should be like:

private ICache _cache;
public HomeController(ICache cache)
{
    this._cache = cache;
}

If your factory contains complex behavior to do the selection, you can still use it inside your Composition Root, but there might not be a reason for the application code to take a dependency on it.

Upvotes: 3

Related Questions