Search code examples
c#abstract-factory

How can factory's have access to other factory's products in abstract factory pattern


Here is a diagram of the pattern im referring to.

In this example for the NYPizzaIngredientFactory, they can only make pizza with ThinCrustDough. How can i make a pizza that could use another factory's ingredients like ThickCrustDough from ChicagoPizzaIngredientFactory. I want to try stay away from builder and stick with abstract factory patterns and factory methods.


Solution

  • Your NYPizzaStore would have to use the ChicagoPizzaIngredientFactory if you want it to be able to use ThickCrustDough.

    If you think about the practicality of this, however, it probably doesn't make sense to have them ship you the ingredients from Chicago.

    In my mind, you have two options:

    1. Have another factory located in NY that can produce thick dough (e.g. NYThickPizzaIngredientFactory). This is because your interface has a single createDough method that takes no arguments so you can't tell it what type of dough to make. It can only make one.
    2. Alter your interface so that the createDough method accepts arguments that can tell the factory what type of dough to create. This is the one I would recommend.

    The type of arguments can also be based on the particular factory. For instance:

    //TDoughArts tells you what type of arguments the factory needs in order to make dough.
    public interface IPizzaIngredientFactory<TDoughArgs> where TDoughArgs : IDoughArgs      
    {
        //....
        IDough CreateDough(TDoughArgs doughArgs);
        //....
    }
    
    public interface IDoughArgs
    {
    
    }
    
    public class NYPizzaDoughArgs : IDoughArgs
    {
        public enum DoughTypes
        {
            Thin = 0,
            Thick = 1
        }
    
        public DoughTypes DoughType { get; set; }
    }
    
    public class NYPizzaIngredientFactory : IPizzaIngredientFactory<NYPizzaDoughArgs>
    {
        //....
        public IDough CreateDough(NYPizzaDoughArgs doughArgs)
        {
            //Make the right dough based on args here
            if(doughArgs.DoughType == DoughTypes.Thin)
                //...
        }
        //....
    }
    

    I whipped this out in a few minutes so check for consistency, but I think you will get the idea.

    You don't have to use generics. You can simply stick with the IDoughArgs interface if you don't want more specificity.

    Usage:

    var factory = new NYPizzaIngredientFactory();
    var args = new NYPizzaDoughArgs();
    args.DoughType = NYPizzaDoughArgs.DoughTypes.Thick;
    var dough = factory.createDough(args);