工厂方法以及在哪里选择要使用哪个工厂
Factory method and where to choose which factory is to be used
我有一个项目涉及不同种类产品的网店。据我了解,如果您有多个 class 继承自一个基础 class,工厂设计模式是可行的方法。我只是难以决定将实际决定使用哪个工厂的逻辑放在哪里。
我已经为不同类型的产品创建了 classes 和工厂 classes。
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
作用于它们中的每一个。问题是要知道我需要从填充函数中填充的数据库中获取产品类型的产品类型。
我能做的是在 ProductFactory 中创建一个函数 public ProductFactory GetFactory(int id)
。但是那时工厂是不能抽象的class。
另一种选择是在产品 class 中创建函数 public static Product GetProduct(int id)
。然后首先确定要使用哪个工厂以及 returns 创建的产品。
但是这两个选项感觉很奇怪。我错过了什么吗?或者其中之一是实际可行的方法?
干杯。
因此请跳过产品 class 中的 Populate
功能。那是工厂的职责。我会和一家工厂 class 一起生产所有类型的产品。 (如果需要,工厂可以调用其他 classes 来帮助创建产品)
类似于:
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);
...
}
}
呃,别想太多了。设计模式应该是您用来创建代码的工具,如果我正确阅读了您的问题,我认为您更多地处于设计模式使用您的状态。
因此,除非该模式对您有帮助,否则不要使您的代码过于复杂。
就是说,如果您确实选择了一种模式,那么您的情况似乎很简单,可以采用 Magnus 的解决方案。
看看这个工厂方法设计模式的例子:http://jayeshtanna.azurewebsites.net/2018/11/25/factory-method-design-pattern/
我有一个项目涉及不同种类产品的网店。据我了解,如果您有多个 class 继承自一个基础 class,工厂设计模式是可行的方法。我只是难以决定将实际决定使用哪个工厂的逻辑放在哪里。
我已经为不同类型的产品创建了 classes 和工厂 classes。
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
作用于它们中的每一个。问题是要知道我需要从填充函数中填充的数据库中获取产品类型的产品类型。
我能做的是在 ProductFactory 中创建一个函数 public ProductFactory GetFactory(int id)
。但是那时工厂是不能抽象的class。
另一种选择是在产品 class 中创建函数 public static Product GetProduct(int id)
。然后首先确定要使用哪个工厂以及 returns 创建的产品。
但是这两个选项感觉很奇怪。我错过了什么吗?或者其中之一是实际可行的方法?
干杯。
因此请跳过产品 class 中的 Populate
功能。那是工厂的职责。我会和一家工厂 class 一起生产所有类型的产品。 (如果需要,工厂可以调用其他 classes 来帮助创建产品)
类似于:
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);
...
}
}
呃,别想太多了。设计模式应该是您用来创建代码的工具,如果我正确阅读了您的问题,我认为您更多地处于设计模式使用您的状态。
因此,除非该模式对您有帮助,否则不要使您的代码过于复杂。
就是说,如果您确实选择了一种模式,那么您的情况似乎很简单,可以采用 Magnus 的解决方案。
看看这个工厂方法设计模式的例子:http://jayeshtanna.azurewebsites.net/2018/11/25/factory-method-design-pattern/