Фабричный метод и где выбрать какую фабрику использовать - PullRequest
3 голосов
/ 20 апреля 2020

У меня есть проект с участием интернет-магазина для различных видов продуктов. Из того, что я понимаю, если у вас есть несколько классов, которые наследуются от одного базового класса, шаблон проектирования фабрики - это путь к go. У меня только проблемы с решением, куда поместить logi c для фактического решения о том, какую фабрику использовать.

Я создал классы и классы фабрики для различных видов продуктов, например:

public class Product
{
    public int ID { get; protected set; }
    public string Name { get; set; }
    public ProductType Type { get; private set; }

    public Product(int id)
    {
        ID = id;
        Populate();
    }

    public virtual void CompleteOrder()
    {
        //SendMailToSupplier();
    }

    private void Populate() 
    {
        //database stuff including setting the type
    }
}

public class DigitalProduct : Product
{
    public DigitalAsset ProductAsset { get; private set; }

    public DigitalProduct(int id, DigitalAsset asset) : base(id)
    {
        ProductAsset = asset;
    }

    public override void CompleteOrder()
    {
        base.CompleteOrder();
        //SendAssetToUser();
    }
}

public class PrintProduct : Product
{
    public PrintInformation Information { get; private set; }

    public PrintProduct(int id, PrintInformation information) : base(id)
    {
        Information = information;
    }

    public override void CompleteOrder()
    {
        base.CompleteOrder();
        //PreparePrintingFlle();
    }
}

public abstract class ProductFactory
{
    public abstract Product CreateProduct(int id);
}

public class GenericProductFactory : ProductFactory
{
    public override Product CreateProduct(int id)
    {
        return new Product(id);
    }
}

public class DigitalProductFactory : ProductFactory
{
    public override Product CreateProduct(int id)
    {
        DigitalAsset asset = GetDigitalAsset(id);
        return new DigitalProduct(id, asset);
    }   

    private DigitalAsset GetDigitalAsset(int id)
    {
        DigitalAsset asset = new DigitalAsset();
        //IO stuff
        return asset;
    }
}

public class PrintProductProductFactory : ProductFactory
{
    public override Product CreateProduct(int id)
    {
        PrintInformation information = GetPrintInformation(id);
        return new PrintProduct(id,information);
    }

    private PrintInformation GetPrintInformation(int id)
    {
        PrintInformation information = new PrintInformation();
        //database stuff
        return information;
    }
}

Теперь, когда заказ выполнен, запускается событие.

public void OrderCompleted(int orderId, List<int> productIds);

Итак, у меня есть список целых чисел, из которых я хочу сделать объект продукта, чтобы я мог вызвать функцию CompleteOrder для каждого из их. Проблема заключается в том, чтобы узнать тип продукта, который мне нужен, чтобы получить тип продукта из базы данных, которая заполнена функцией заполнения.

Что я мог бы сделать, это создать функцию public ProductFactory GetFactory(int id) в ProductFactory. Но тогда фабрика не может быть абстрактным классом.

Другим вариантом было бы создание функции public static Product GetProduct(int id) в классе продукта. Затем сначала выясняется, какую фабрику использовать, и возвращает созданный продукт.

Но оба эти варианта кажутся странными. Я что-то пропустил? Или один из них - настоящий путь к go?

Приветствия.

Ответы [ 3 ]

2 голосов
/ 20 апреля 2020

Поэтому пропустите функцию Populate в классе Product. Таковы обязанности фабрики. И я бы go с одним фабричным классом для создания всех типов продуктов. (Фабрика может при необходимости вызвать другие классы, чтобы помочь создать продукт)

Что-то вроде:

public class ProductFactory
{
     public Product GetProductById(int id)
     {
          var dbProduct = FetchFromDb(id);
          switch(dbProduct.Type)
          {
              case "Print"
                 return CreatePrintProduct(dbProduct);
              case "Digital"
                 return CreateDigitalProduct(dbProduct);
          }
     }


     private DigitalProduct CreateDigitalProduct(DbEntity dbProduct)
     {
         var product = new DigitalProduct(dbProduct.Id);
         //Initialize the product

         return product;
     }

     //You might also want a batch function to avoid calling the database for each product.
     public IEnumerable<Product> GetProductByIds(IEnumerable<int> ids)
     {
          var dbProducts = FetchFromDb(ids);
          ...
     }
}
0 голосов
/ 20 апреля 2020

посмотрите на этот пример шаблона проектирования фабричного метода: http://jayeshtanna.azurewebsites.net/2018/11/25/factory-method-design-pattern/

0 голосов
/ 20 апреля 2020

Эх, просто не переусердствуйте. Шаблоны проектирования должны быть инструментами, которыми вы владеете для создания своего кода. Если я правильно прочитал ваш вопрос, я думаю, что вы в большей степени находитесь в состоянии шаблона проектирования, которым владеете.

Так что, если шаблон не поможет вам, не переусердствуйте. усложните свой код этим.

Тем не менее, если вы решите выбрать go для шаблона, ваша ситуация кажется достаточно простой до go для решения Магнуса.

...