What methods should go in my DDD factory class?


Question

I am struggling to understand what my factory class should do in my DDD project. Yes a factory should be used for creating objects, but what exactly should it be doing. Consider the following Factory Class:

    public class ProductFactory
    {
        private static IProductRepository _repository;

        public static Product CreateProduct()
        {
            return new Product();
        }

        public static Product CreateProduct()
        {
            //What else would go here?
        }

        public static Product GetProductById(int productId)
        {
            //Should i be making a direct call to the respoitory from here? 
            Greener.Domain.Product.Product p = _repository.GetProductById(productId);
            return p;
        }
    }

Should i be making a direct call to the repository from within the factory?

How should i manage object creation when retriving data from a database?

What do i need to make this class complete, what other methods should i have?

Should i be using this class to create the Product object from the domain and repository from right?

Please help!

1
12
3/4/2009 3:06:10 PM

Exper Answer

In the example given above, I'm a little unclear on the distinction between your factory and the repository. I wonder if you shouldn't simply add CreateProduct as a method to the repository, and using DI to push the repository into code that needs it? If the factory isn't doing anything, etc...

Or if you just want it to act as a globally registered repository, perhaps something like:

public static IFooRepository Default {get;private set;}
public static void SetRepository(IFooRepository repository) {
    Default = repository;
}

(in my mind it seems clearer to separate the "set" in this case, but you don't have to agree)

and have the callers use var product = YourFactory.Default.CreateProduct(); etc

0
3/4/2009 3:19:38 PM

Should i be making a direct call to the repository from within the factory?

No, don't use a factory when your retrieving stuff, use a factory only when you are creating it for the first time.

How should i manage object creation when retriving data from a database?

Pass that data into the factory, if it is required for the object's initial creation.

What do i need to make this class complete, what other methods should i have?

Many factories are not even individual classes, they are just methods that provide object creation. You could fold the factory method into another class, if you felt like it was just going to call a parameterless constructor.

Should i be using this class to create the Product object from the domain and repository from right?

The repository is for getting (in a sense creating) existing objects, the factory is for the first time you create an object.

Initially many factories won't do much except call a constructor. But once you start refactoring and/or creating larger object hierarchies, factories become more relevant.

Explanation and Example:

For instance, in the project I'm working on I have an excel processor base class and many subclasses implementing that base class. I use the factory to get the proper one, and then call methods on it, ignorant of which subclass was returned.(Note: I changed some variable names and gutted/altered a lot of code)

Processor base class:

public abstract class ExcelProcessor
{
      public abstract Result Process(string ExcelFile);
}

One of the Processor subclasses:

public class CompanyAExcelProcessor : ExcelProcessor
{
     public override Result Process(string ExcelFile)
     {
      //cool stuff
     }
}

Factory:

 public static ExcelProcessor CreateExcelProcessor(int CompanyId, int CurrentUserId)
 {
      CompanyEnum company = GetCompanyEnum(CompanyId);
      switch (company)
      {
           case CompanyEnum.CompanyA:
                return new CompanyAExcelProcessor();
           case CompanyEnum.CompanyB:
                return new CompanyBExcelProcessor();
           case CompanyEnum.CompanyC:
                return new CompanyCExcelProcessor(CurrentUserId);
           //etc...
      }
 }

Usage:

ExcelProcessor processor = CreateExcelProcessor(12, 34);
processor.Process();

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon