服务定位器模式与抽象工厂模式有什么不同?

Is the Service Locator pattern any different from the Abstract Factory pattern?

乍一看,服务定位器模式在我看来与抽象工厂模式相同。它们似乎都有相同的用途(您查询它们以接收抽象服务的实例),当我阅读依赖项注入时,它们都被提到过。

然而,我已经看到服务定位器模式被描述为一个糟糕的想法,但是在至少一个主要的依赖注入框架中看到了对抽象工厂模式的直接支持。

如果它们不一样,有什么区别?


在研究这些模式时,我偶然发现了同样的问题。我认为服务定位器和工厂之间的主要区别(不管它是否抽象):

服务定位器

  • "locates"现有的依赖项(服务)。尽管服务可以在解决过程中创建,但对客户没有任何影响,因为:
  • 服务定位器的客户端不拥有依赖项的所有权。

工厂

  • 创建依赖项的新实例。
  • 工厂的客户机拥有依赖关系的所有权。

抽象工厂

  • 与常规工厂相同,只是不同的部署可能使用不同的抽象工厂实现,允许在这些不同的部署中实例化不同的类型(您甚至可以在运行时更改抽象工厂的实现,但这通常不是它的使用方式。)


从我目前所读到的内容来看,我认为不同之处在于:

服务定位器模式

  • 显式支持应创建/返回哪些具体对象的注册
  • 通常有一个通用接口,允许用户请求任何抽象类型,而不是特定类型
  • 可能是具体的

抽象工厂模式

  • 可能不支持注册——这取决于具体的实现是否支持,并且可能不会在抽象接口上公开。
  • 对于特定的抽象类型,通常有多个get方法
  • 本身不是具体的(当然会有具体的实现)


实际上,这两种模式之间有着明显的区别。众所周知,这两种模式都用于避免具体类型的依赖性。

但在阅读后

  • 敏捷软件开发、原理、模式和实践[书],作者:Rober C.Martin
  • Martin Fowler在http://martin fowler.com/articles/injection.html上对控制容器和依赖注入模式的反转
  • 模式识别:抽象工厂还是服务定位器?[文章]作者:Mark Seeman,网址:http://blog.ploeh.dk/2010/11/01/patternrecognitionabstractfactorservicelocator/
  • Erich Gamma等人的设计模式[书]

出现了一些严重的矛盾:

Seemann说:"抽象工厂是一个泛型类型,create方法的返回类型由工厂本身的类型决定。换句话说,构造的类型只能返回单个类型的实例。"

虽然rober c.martin没有提到任何关于泛型类型的内容,而且他的书中的factory示例允许创建多个对象类型的实例,使用factory.make()中的键字符串作为参数来区分这些对象。

gamma说抽象工厂的目的是"为创建相关或依赖对象的族提供一个接口,而不指定它们的具体类"。值得一提的是,gamma抽象工厂示例违反了Martin所述的接口隔离原则(ISP)。一般来说,isp和solid是更现代的原则,或者可能是为了简单起见而省略。

伽玛和马丁的作品先于西曼的,所以我认为他应该遵循已经做出的定义。

虽然Fowler提出服务定位器作为实现依赖倒置的一种方法,但Seemann认为它是一种反模式。gamma和martin都没有提到服务定位器。

然而,Seemann和Fowler在服务定位器中同意需要一个配置步骤来注册concretes类的实例,该实例是稍后请求此类对象时将返回的实例。Martin或Gamma在其抽象工厂的定义中没有提到这个配置步骤。抽象工厂模式假定每次请求此类对象时都要实例化一个新对象。

结论

服务定位器和抽象工厂之间的主要区别在于,抽象工厂假设一个新对象被实例化,在每个请求时返回,并且服务定位器需要配置一个对象实例,并且每次返回相同的实例时。


来自:http://blog.ploeh.dk/2010/11/01/patternrecognitionabstractFactoryorServiceLocator/

An Abstract Factory is a generic type, and the return type of the Create method is determined by the type of the factory itself. In other words, a constructed type can only return instances of a single type.

A Service Locator, on the other hand, is a non-generic interface with a generic method. The Create method of a single Service Locator can return instances of an infinite number of types.