但是,我看到服务定位器模式被描述为一个糟糕的想法, 但是至少有一个主要的依赖注入框架直接支持抽象工厂模式。
如果它们不同,那么它们有什么区别?
在研究这些模式时,我遇到了同样的问题。我认为 Service Locator 和 Factory(无论它是否是抽象的)之间的主要区别在于:
根据我目前的了解,我认为两种模式的区别如下:
服务定位器模式(Service Locator pattern)
抽象工厂模式(Abstract Factory pattern)
来源:http://blog.ploeh.dk/2010/11/01/PatternRecognitionAbstractFactoryorServiceLocator/
抽象工厂是一种通用类型,Create方法的返回类型由工厂本身的类型确定。换句话说,构造出的类型只能返回单个类型的实例。
另一方面,服务定位器是一个非泛型接口,具有一个泛型方法。单个服务定位器的Create方法可以返回无限数量的类型的实例。
Martin Fowler描述了几种服务定位器模式的实现方式,其中大多数是具体类,通过static
方法进行配置和调用。我认为我们可以忽略这些变化,关注他使用依赖注入的最终示例,这是一种更现代的方法。我们可以将其与GoF书籍中的抽象工厂模式进行比较。
抽象工厂的区别特征是一组相关产品的固定集合。相反,服务定位器具有无限的不相关产品集合。这使得服务定位器更像一个黑盒子,并导致该模式的主要批评:它隐藏了API的依赖关系。当服务定位器作为动态注册表实现时,客户端可能会请求不存在的产品。这在抽象工厂中是不可能的。
在抽象工厂和服务定位器之间做出选择时,前者是更可取的模式。但这是一种虚假的二分法,因为还有更多的选择。这两种模式都依赖于依赖注入,但DI在没有它们的情况下运行得更好。
注入(Injection)是实现控制反转(Inversion of Control,IoC)的机制。IoC是依赖反转的理想形式,因为它最大程度地减少了客户端的复杂性并提供了最高级别的抽象化。服务定位器(Service Locator)和抽象工厂(Abstract Factory)是两种实现依赖反转的机制,但是它们都不具备控制反转的优点,并且从理想情况来看都是不可取的。
有关IoC与DI的更多信息,请参见:控制反转 vs 依赖注入。
有关抽象工厂和服务定位器的缺陷信息,请参见:依赖注入代码味道。