0

I am still trying to get some experience with DI. Let me illustrate my situation and you can give me advice on whether I am using DI and Abstract Factory correctly.

I need to create IModels at runtime. So I am going to use DI to inject an IModelFactory into my objects. But the concrete implementation of my IModels depend on IDataManagers. This is fine, I can inject IDataManagerFactory into my IModelFactory implementation. Moreover, since IDataManager implementations depend on IRepository's. I can inject IRepositoryFactory into my IDataManager implementation.

Is this kind of Abstract Factory chaining acceptable design? Or is this a warning I am going down the wrong path? All the examples I see online are basically of Factories that create objects with parameter dependencies or none at all.

// Products
class Model : IModel
{
    IDataManger dm;

    ctor(IDataMangerFactory dmFactory)
    {
        dm = dmFactory.Create();
    }
}

class DataManager : IDataManager
{
    IRepository repo;

    ctor(IRepositoryFactory repoFactory)
    {
        repo = repoFactory.Create();
    }
}

class Repo : IRepository
{
    ctor() {}
}

// Factories
class RepoFactory : IRepositoryFactory
{
    public IRepository Create()
    {
        return new Repo();
    }
}

class DmFactory : IDataManagerFactory
{
    IRepositoryFactory repoFactory;

    ctor(IRepositoryFactory factory)
    {
       repoFactory = factory;
    }

    public IDataManager Create()
    {
        return new DataManager(repoFactory);
    }
}

class ModelFactory : IModelFactory
{
    IDataManagerFactory dmFactory;

    ctor(IDataManagerFactory factory)
    {
       dmFactory = factory;
    }

    public IModel Create()
    {
        return new Model(dmFactory);
    }
}

// register the classes into the DI
// Application root instantiates Consumer. DI resolves.

// Consumer
class Consumer
{
    public BindableCollectionOfModels {get;set;}

    IModelFactory modelFactory;
    ctor(IModelFactory factory)
    {
         modelFactory = factory;
    }

    public void UserClicksCreateNewModelInUI()
    {
        var model = modelFactory.Create();
        BindableCollectionOfModels.Add(model);
    }
}

My gut tells me this can go either way. I am writing a ton of extra code, adding complexity, etc., and something doesn't feel right about it. On the other hand, I am gaining the ability to trade out implementations all along the chain. This is good in my project because we are on a time-frame to get prototypes in front of the customer, but once the customer sees how it works, we have time to flesh out the implementation and refine it. So using this method we can simply trade messy, inefficient implementations with refined, thorough implementations as we move forward with the project.

My question is: is this good use of Abstract Factories and DI or am I doing it wrong? If so why? If not, explain.

1 Answer 1

1

I'm more used to seeing dependency injection working in terms of the instantiated objects, rather than the factories (unless the components that you inject into need to create these objects dynamically post-wiring)

e.g. I would use the factories to instantiate the components up front, and then wire them together e.g (in pseudo-Scala, but the intent should be clear)

val repoFactory = new RepoFactory()
val dmFactory = new DataManagerFactory()

val repo = repoFactory.newRepo()
val dm = dmFactory.newManager(repo)
val model = new Model(dm)

I would inject the factory instead if the wired-up components need to create subsequent components on the fly e.g.

val model = new Model(new EntityFactory())

// post-wiring...
if (condition) {
   val entity = model.newEntity()
   entity...
}
2
  • There's something wrong with the last sentence of your answer. There are two possible fixes, and I don't know which one applies. Apr 20, 2016 at 14:24
  • @RobertHarvey - can you elaborate. pls ? I'm not sure I can see the issue you're referring to Apr 20, 2016 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.