0

以下代码有什么问题?

public class DeDoper {
    public boolean wackapediaOkToday() {
        DnsResolver resolver =  ResolverFactory.getInstance().makeResolver();
        return resolver.getIpAddressFor("wackapedia.org").equals("123.456.78.9");
    }
}

为什么首选这个版本?

public class DeDoper {
    @InjectService
    private DnsResolver resolver;
    
    public boolean wackapediaOkToday() {
        return resolver.getIpAddressFor("wackapedia.org").equals("123.456.78.9");
    }
}

我可以轻松地模拟 ResolverFactory.makeResolver() 这与设置解析器是最新的示例相同。

这就是ProQuest.biz的这篇文章中所说的:

WackapediaOkToday 的 [第一个] 版本非常笼统地说,是“注入”了一个 DnsResolver(尽管公认它不太像打针,而更像是向服务员索要支票)。但它确实解决了测试问题,以及“一路乌龟”的问题。

链接到工厂 但是在这个 [第一个版本] 方法中,我们实际上是“链接”到工厂类。(更糟糕的是,如果我们的工厂创建的对象依次具有依赖关系,我们可能必须在工厂内部引入新工厂。)我们还没有完全“反转”我们的控制,我们仍然从内部调用(控制)工厂我们的班级。

所需要的是一种完全摆脱我们类中的控制的方法,并让他们告诉他们正在得到什么(对于他们的依赖项)。

4

1 回答 1

2

假设您有一个可以有多种实现的服务,例如“FileLocator”。这有一个 FilesystemFileLocator,它将文件根目录的路径作为参数,还有一个 S3FileLocator,它将您的 S3 凭据作为参数。前者需要你编写一个服务定位器来确定你想要哪个版本,然后返回它。反过来,该代码必须获取您的数据,构建适当类型的文件定位器等。您正在做 IOC 容器应该为您做的事情。最重要的是,您已经注入了对该特定创建方法的依赖。

在第二个版本中,您已经(通过注释或 XML)定义了您想要的文件定位器类型。IOC 容器为您实例化和管理它。您必须维护的代码更少。如果要引入第三种类型的 FileLocator,工作量也会减少。或者也许你重构你的代码,使文件定位器是单例的,或者如果它们是单例的,它们现在是新定位器的工厂,或者你可能想要合并定位器实例。在所有这些情况下,如果您使用 IOC 容器,破损将更少。

于 2013-03-03T20:29:00.377 回答