服务定位器不仅仅是全局变量/状态吗?

时间:2009-06-10 21:38:49

标签: language-agnostic dependency-injection service-locator

为了解码代码,您可以使用服务定位器,但这与全局变量/状态不同吗?

我知道这些通常会运行接口,所以你传入一个接口并获得一个具体的类,但我的问题仍然存在。

例如:

class Something {

    void DoSomething() {
        IMyType myType = ServiceLocator.GetSerivceTypeOf(IMyType);
    }
}

这里的类需要在其他地方创建的MyType,但不是通过链(通过构造函数等......)传递MyType,而是以这种方式获取它。

我在职业生涯早期作为开发人员问过这个问题 - 在此之前我不会遇到这种模式。安东尼已经在服务定位器上发表了我的观点(因此现在是选定的答案) - 实际上我认为它们像其他人一样反模式。所提供的链接是一个很好的起点 - 但是在所有这些时间之后,它有点回答我自己的问题,它们充当全球状态,应该避免。首选标准依赖注入;)

3 个答案:

答案 0 :(得分:3)

通常备份服务定位器模式的名称服务确实使用了全局的名称空间。

然而,必须考虑“全局变量”被认为是坏的原因。其中许多都围绕着在程序中的任何位置修改全局变量的能力。但是,大多数命名服务都可以限制对绑定对象的修改。对象本身可能是不可变的。

服务定位器不仅仅是一个全局变量,它是一个专业化。而这种专业化倾向于缓解全局变量可能产生的许多问题。

答案 1 :(得分:2)

是的,它们是全局变量。复杂的,但他们仍然有相同的基本缺点。因此,最好使用依赖注入。

有关构造函数注入的替代方法的更详细讨论,另请参阅问题What’s the difference between the Dependency Injection and Service Locator patterns?

以及其他网页Singletons are Pathological LiarsDependency Injection pattern

答案 2 :(得分:1)

在某些时候,你需要一个具体的实现来做一些工作。从某种意义上说,该服务是“全球性的”,它对您的应用程序是“可用的”。但是您不必将其作为代码中的全局变量。

您可以撤消参数。如果您需要访问应用程序中的服务,您将使用什么模式来访问它,而不将其绑定到具体实现。没有太多选择。

某些资源对您的应用程序本质上是“全局的”,采用操作系统,文件系统,窗口系统,......

讨论比解决问题更具哲学性。无论如何,希望它有所帮助。