Factory Pattern but with object Parameters

前端 未结 7 1881
春和景丽
春和景丽 2021-02-02 11:05

Take the following classic factory pattern:

public interface IPizza
{
    decimal Price { get; }
}

public class HamAndMushroomPizza : IPizza
{
    decimal IP         


        
7条回答
  •  被撕碎了的回忆
    2021-02-02 12:01

    First of all, it seems strange to me that an abstract class PizzaFactory contains an abstract general method CreatePizza that takes a parameter of a more concrete type ItalianPizzaFactory.PizzaType.

    To cover the problem I have just mentioned and the problem stated in the post, I would suggest the following approach.

    public struct PizzaDefinition
    {
        public readonly string Tag; 
        public readonly string Name;
        public readonly string Description;
        public PizzaDefinition(string tag, string name, string description)
        {
            Tag = tag; Name = name; Description = description;
        }
    }
    
    public abstract class PizzaFactory
    {
        public abstract IEnumerable GetMenu();
        public abstract IPizza CreatePizza(PizzaDefinition pizzaDefinition);
    }
    
    
    public class ItalianPizzaFactory : PizzaFactory
    {
        public enum PizzaType
        {
            HamMushroom,
            Deluxe,
            Hawaiian
        }    
    
        public override IEnumerable GetMenu()
        {
            return new PizzaDefinition[] {
                new PizzaDefinition("hm:mushroom1,cheese3", "Ham&Mushroom 1", "blabla"),
                new PizzaDefinition("hm:mushroom2,cheese1", "Ham&Mushroom 2", "blabla"),
                new PizzaDefinition("dx", "Deluxe", "blabla"),
                new PizzaDefinition("Hawaian:shrimps,caramel", "Hawaian", "blabla")
            };
        }
    
        private PizzaType ParseTag(string tag, out object[] options){...}
    
        public override IPizza CreatePizza(PizzaDefinition pizzaDefinition)
        {
            object[] options;
            switch (ParseTag(pizzaDefinition.Tag, out options))
            {
                case PizzaType.HamMushroom:
                    return new HamAndMushroomPizza(options);
                case PizzaType.Hawaiian:
                    return new HawaiianPizza();
                default:
                    throw new ArgumentException("The pizza" + pizzaDefinition.Name + " is not on the menu.");
            }
        }
    }
    
    

    As you see, the ParseTag() method may be of arbitrary complexity, parsing a plain text or an encrypted value. Or the Tag field can be a simple int that is mapped internally to some pizza recipe table, with whole different recipes for even slightly changed pizza content.

提交回复
热议问题