它是不好用的serviceLocation而不是构造函数注入,以避免工厂类的书写负荷(Is it b

2019-08-22 23:30发布

现在,我们使用DI / IOC,当我们需要额外的参数传递给我们使用一个工厂类,如构造

public class EmailSender 
{
    internal EmailSender(string toEmail, string subject,String body, ILogger emailLogger)
    {.....} 
}

public class EmailSenderFactory
{
    ILogger emailLogger;
    public EmailSenderFactory(ILogger emailLogger)
    { 
        this.emailLogger = emailLogger;
    }
    public EmailSender Create(string toEmail, string subject, string body) 
    {
        return new EmailSender(toEmail, subject, body, emailLogger);
    }
}

现在,这个问题是我们最终建立一个整体洛塔工厂类,人们总是不知道使用它们(他们有时新起来自理)。 什么是编码这样的类的最大劣势:

public class EmailSender 
{
    EmailLogger logger = IoC.Resolve<ILogger>();
    internal EmailSender(string toEmail, string subject,String body)
    {.....} 
}

临:我们现在可以放心地使用构造而无需工厂类缺点:我们引用了服务定位器(我不担心可测试性,其易于使用的一个模拟的容器作为容器支撑服务)。

是否有一个原因,一些大臭气熏天在那里,为什么我们不应该这样做?

编辑:有点想法之后,我突然意识到当具有私有构造函数,通过嵌套工厂类的,我可以继续实施和工厂一起,并阻止人们创造不当班,所以这个问题已经变得有些没有实际意义。 所有关于SL是脏点的点,当然是真实的,所以下面的解决方案让我开心:

public class EmailSender 
{
    public class Factory
    {
        ILogger emailLogger;
        public Factory(ILogger emailLogger)
        { 
            this.emailLogger = emailLogger;
        }
        public EmailSender Create(string toEmail, string subject, string body) 
        {
            return new EmailSender(toEmail, subject, body, emailLogger);
        }
    }
    private EmailSender(string toEmail, string subject,String body, ILogger emailLogger)
    {
    } 
}

Answer 1:

是的 - 它是坏的。

  • 为什么写所有的代码时,你可以让框架做的工作? 所有IoC.Resolve()调用是多余的,你不应该给他们写。
  • 另一个更重要的方面,就是你的组件与您的服务定位。

    现在您无法实例化他们就是这样 - 你每次需要使用一个组件时需要完全设置服务定位到位。

  • 最后,机器人至少 - 您的SL代码是洒在你的代码库这是不是一件好事,因为当你想改变一些东西,你必须在多个地方看看。


Answer 2:

我能想到的(不只是寻找与服务定位器一般问题)最大的原因是,它不是我作为你的类的用户会期望 。

元的讨论:
有些DI框架( 吉斯为例)将建立工厂给你 。

有些人主张从“注射的”分离“newable”。



Answer 3:

我不太清楚这个强大的“这是不好的”的回答给了由克日什托夫。 我觉得有一些取舍和偏好在那里绝对没有它们归类为好还是坏。

  • 我不认为这是更多余写比写特定的构造函数或属性的注射机构的IoC.Resolve()调用。
  • 这一次,我不得不承认,你是绑在服务定位器,你有实例化一个类之前设置它。 然而:
    • 你可以用更具体的接口分离的服务定位器。 从而降低耦合与一个巨大的服务定位器为您的系统的每一个服务
    • 是啊,如果你使用DI机制,你会删除所有这些IoC.Resolve(),但你仍然将不得不使用一种容器的实例化你的“主”服务。 该DI具有拦截这些调用,不是吗?
    • 您的服务定位器可以(应该?)是“自动配置”,或者至少,很容易成立。
  • 见上面的“更具体的接口分离的服务定位器...”点。

我想用一个服务定位器确实隐藏你的依赖在类中,而不是通过构造暴露他们。 而且在我看来是一个不方便的,因为你不知道你的类是失去了一些东西,直到服务定位器调用没有配置。

但是DI的事情是不是免费的那种代码黑暗的。 当您使用DI,实在是不明显,以了解这些依赖只是“似乎”(DI魔法)在构造函数。 通过使用SL,你至少能看到这些相关的来源。

但尽管如此,测试,揭露她的建设者这些依赖类时,你(几乎)不能错过它。 这是不使用服务定位器的情况。

我不是说克日什托夫·错了,因为我同意他的说法为最。 但我敢肯定,使用服务定位器不一定是坏的“设计”,当然不是简单地坏。

菲尔



文章来源: Is it bad to use servicelocation instead of constructor injection to avoid writing loads of factory classes