【问题标题】:How to implement factory pattern that dynamically loads new products (open close principle)?如何实现动态加载新产品的工厂模式(开闭原则)?
【发布时间】:2020-08-03 06:18:04
【问题描述】:

在工厂方法中,我们必须编写 switch case 或 if 语句来决定创建和返回哪个实例。这违反了打开关闭原则,因为 - 每次添加新产品时,都必须更新工厂方法代码。

有什么方法可以使这种动态化——这样添加新产品就不需要对工厂方法进行任何更改?

例如:在 python 中,我们可以导入包含所有可用产品列表的包。工厂方法将所有可用产品及其类加载到 dict 数据结构中。因此,添加新产品时无需更改工厂代码。只需将产品添加到工厂用于导入产品类的包代码中即可。

【问题讨论】:

  • 你可以......但这真的取决于你想要多少。您可以使用反射来查找从基类型派生的所有类型。并根据一些标准......比如类型名称或类型上的公共常量标识符决定激活哪一个。但是它有点重。即使它是“开闭”。我建议使用这些原则作为帮助你的工具。不是将您限制在难以阅读、理解和维护的代码中。如果你想沿着反射路径走。如果您愿意,我可以添加一个示例作为答案。

标签: c# design-patterns factory-pattern open-closed-principle


【解决方案1】:

我不知道这是否对您有帮助,但如果您在产品类上使用无参数构造函数,则可以使用此示例。当然,实施可以根据您的需要而有所不同。产品类别也可以在不同的程序集中定义。

/// <summary>
/// Product common interface.
/// </summary>
public interface IProduct
{
}
/// <summary>
/// Definition of an apple product.
/// </summary>
public class Apple : IProduct
{
    public string Gauge { get; set; }
}
/// <summary>
/// Definition of a pear product.
/// </summary>
public class Pear : IProduct
{
    public string Sweetness { get; set; }
}
/// <summary>
/// Factory class.
/// </summary>
public class ProductFactory
{
    /// <summary>
    /// List of product types found in the current assembly.
    /// </summary>
    private static IList<Type> ProductTypes = new List<Type>();
    /// <summary>
    /// Initializes the list of product types.
    /// </summary>
    public static void Initialize()
    {
        foreach (Type prodType in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
            .Where(prodType => prodType.GetInterfaces().Contains(typeof(IProduct))))
        {
            ProductTypes.Add(prodType);
        }
    }
    /// <summary>
    /// Factory Get function.
    /// </summary>
    /// <typeparam name="T">Generic implementing IProduct.</typeparam>
    /// <returns>Instance of the generic implementing IProduct.</returns>
    public static T GetProduct<T>() where T : IProduct, new()
    {
        var productType = ProductTypes.Where(x => x.Name.Equals(typeof(T).Name)).FirstOrDefault();
        if (productType is null) return default;
        return (T)Activator.CreateInstance(productType);
    }
}
/// <summary>
/// Entrypoint class.
/// </summary>
public static class Program
{
    /// <summary>
    /// Entrypoint method.
    /// </summary>
    public static void Main(string[] args)
    {
        // Initialize the list of product types.
        ProductFactory.Initialize();
        // Get an apple.
        var apple = ProductFactory.GetProduct<Apple>();
        // Get a pear.
        var pear = ProductFactory.GetProduct<Pear>();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 2021-08-24
    • 2016-02-01
    相关资源
    最近更新 更多