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

5
为了解耦代码,你可以使用服务定位器,但这不是全局变量/状态吗?
我知道这些通常使用接口运行,因此你传入一个接口并获取一个具体类,但我的问题仍然存在。
例如:
class Something {

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

这里的类需要MyType,但是不是通过构造函数等方式将MyType传递下来,而是以这种方式获取。

我在作为开发人员的职业生涯早期就提出了这个问题 - 在那之前,我还没有遇到过这种模式。安东尼已经表达了我的观点(因此现在被选为答案),即服务定位器是反模式,就像其他人一样。提供的链接是一个很好的起点 - 但是为了回答自己的问题,经过这么长时间,它们作为全局状态应该被避免。更喜欢标准的依赖注入 ;)


举个例子可能会让讨论更加热烈一些。 - Marcus Stade
3个回答

3

问题不在于服务定位器是“最佳”模式,或者它是否比依赖注入更好。问题在于它是否与全局变量相同(它不是,-1),如果不是,那么它是否更好。 - erickson
如果“ServiceLocator”不是全局变量,那么它是什么?你能提供更详细讨论的链接吗?考虑使用此模式的人应该了解首选替代方法,因此提供了讨论更多细节的链接。 - Anthony

3

通常支持服务定位器模式的命名服务确实使用全局命名空间。

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

服务定位器不仅仅是全局变量,它是一种专门化。这种专门化倾向于缓解许多可能由全局变量引起的问题。


3
服务定位器的主要问题在于它隐藏了依赖关系 (http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/)。服务定位器对于缓解这个问题没有任何作用。而且,除非将其再次变为可变的,否则很难替换模拟服务进行测试,这样一来,修改问题又会回来。 - Anthony
1
当然,但这不是这个问题所问的。这里的对比是全局变量和命名服务,而不是命名服务与世界。 - erickson

1

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

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

有些资源本质上是对应用程序“全局”的,例如操作系统、文件系统、窗口系统等。

这个讨论更多的是哲学性的,而不是解决问题的。无论如何,希望它有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接