首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我是否可以使用属性,让我的工厂知道它可以/应该实例化什么,而不违反“松散耦合”规则?

我是否可以使用属性,让我的工厂知道它可以/应该实例化什么,而不违反“松散耦合”规则?
EN

Stack Overflow用户
提问于 2010-12-08 20:47:22
回答 4查看 2.8K关注 0票数 3

我已经在我的项目中实现了一个工厂,最近有人建议我在我的类上使用属性,这样工厂就可以确定实例化哪个类并传回。我是开发领域的新手,试图严格遵循松耦合规则,我想知道依赖“钩子”(属性)是否与此背道而驰?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-12-08 21:05:41

我不认为使用属性会增加工厂和它创建的类之间的耦合度,事实上,它会减少这里的耦合度,因为工厂会在运行时通过属性发现信息。如果有什么不同的话,那就是简单地交换为耦合到属性而创建的类之间的耦合。也就是说,我不确定这到底能为你买到什么。工厂的要点是将创建逻辑本地化在一个地方。通过将其放入属性中,您再次将其散布到代码中,这在一定程度上违背了工厂的目的:现在,您必须同时查看工厂属性,以了解对象是如何创建的。

当然,我可能误解了你的问题。您的意思可能是,一个类使用其属性上的属性来指示哪些属性需要由工厂实例化。在这种情况下,您将替换一些用于进行依赖注入的配置驱动机制。我当然可以看到这可能有用的地方;让工厂发现对象的依赖关系,并在运行时自动创建它们。在这种情况下,您将略微增加代码的整体耦合性,因为现在属性和工厂之间存在以前不存在的依赖关系。总体而言,您可能会降低代码复杂性,因为您不需要为每个类编写特定的代码来提供其特定的依赖项或从配置文件中发现它们。

如果你问使用属性是否是一个好主意,我想我们可能需要更多的信息,但既然你似乎只问你是否会违反OO原则,我不这么认为。我不认为它会增加工厂和要创建的类之间的耦合,而只是略微增加代码的整体耦合。工厂本质上比其他类需要更多的耦合。记住,它是松耦合的,而不是解耦的。未耦合的代码不会做任何事情。您需要类之间的关系才能使任何事情发生。

票数 3
EN

Stack Overflow用户

发布于 2010-12-08 21:05:59

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

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

代码语言:javascript
运行
复制
[ProductAttribute(1)]
public class MyFirstProduct : IProduct
{
}

[ProductAttribute(2)]
public class MySecondProduct : IProduct
{
}

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

代码语言:javascript
运行
复制
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;
    }
}

这样做之后,您可以使用该工厂来创建产品,如下所示:

代码语言:javascript
运行
复制
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();
    }
}

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

票数 7
EN

Stack Overflow用户

发布于 2013-03-28 23:18:51

下面是我用来基于属性值创建具体实例的工厂实现。它还使用参数实例化。

代码语言:javascript
运行
复制
class ViewFactory
{
    public static IView GetViewType(string PropertyValue, SomeOtherObject parentControl){
    Assembly assembly = Assembly.GetAssembly(typeof(ViewFactory));
    var types = from type in assembly.GetTypes()
                where Attribute.IsDefined(type,typeof(ViewTypeAttribute))
                select type;

    var objectType = types.Select(p => p).
        Where(t => t.GetCustomAttributes(typeof(ViewTypeAttribute), false)
            .Any(att => ((ViewTypeAttribute)att).name.Equals(PropertyValue)));

    IView myObject = (IView)Activator.CreateInstance(objectType.First(),parentControl);
    return myObject;
}
}

[ViewTypeAttribute("PropertyValue", "1.0")]
class ListboxView : IView
{


public ListboxView(FilterDocumentChoseTypeFieldControll parentControl)
{

}       
public override void CreateChildrens()
{

}

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4387573

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档