我可以使用属性,以便我的工厂知道它可以/应该实例化而不破坏"松散耦合"规则吗?

pgh*_*ech 3 c# factory-pattern

我在我的项目中实现了一个工厂,最近建议我在我的类上使用属性,以便工厂可以确定要实例化和传回的类.我是开发世界的新手,并试图严格遵循松散耦合的规则,我想知道是否依赖"钩子"(作为属性)违背了这一点?

Ste*_*ven 6

装饰工厂的产品类可以使开发更容易,这是我有时会做的事情.当必须基于存储在数据库中的唯一标识符创建产品时,这尤其有用.必须在该唯一ID和产品类之间建立映射,并且使用属性使其非常清晰且可重用.除此之外,它允许您添加产品类,而无需更改工厂.

例如,您可以像这样装饰您的类:

[ProductAttribute(1)]
public class MyFirstProduct : IProduct
{
}

[ProductAttribute(2)]
public class MySecondProduct : IProduct
{
}
Run Code Online (Sandbox Code Playgroud)

你可以这样实现你的工厂:

public class ProductFactory : IProductFactory
{
    private static Dictionary<int, Type> products =
        new Dictionary<int, Type>();

    static ProductFactory()
    {
        // Please note that this query is a bit simplistic. It doesn't
        // handle error reporting.
        var productsWithId =
          from type in 
              Assembly.GetExecutingAssembly().GetTypes()
          where typeof(IProduct).IsAssignableFrom(type)
          where !type.IsAbstract && !type.IsInterface
          let attributes = type.GetCustomAttributes(
            typeof(ProductAttribute), false)
          let attribute = attributes[0] as ProductAttribute
          select new { type, attribute.Id };

        products = productsWithId
            .ToDictionary(p => p.Id, p => p.type);
    }

    public IProduct CreateInstanceById(int id)
    {
        Type productType = products[id];

        return Activator.CreateInstance(productType) as IProduct;
    }
}
Run Code Online (Sandbox Code Playgroud)

完成此操作后,您可以使用该工厂创建如下产品:

private IProductFactory factory;

public void SellProducts(IEnumerable<int> productIds)
{
    IEnumerable<IProduct> products =
        from productId in productIds
        select factory.CreateInstanceById(productId);

    foreach (var product in products)
    {
        product.Sell();
    }
}
Run Code Online (Sandbox Code Playgroud)

我过去曾使用过这个概念,例如根据数据库标识符创建发票计算.该数据库包含每种发票类型的计算列表.实际计算是在C#类中定义的.