42

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

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

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

4

5 回答 5

46

在调查这些模式时,我偶然发现了同样的问题。我认为可以在 Service Locator 和 Factory 之间找到主要区别(无论它是否抽象):

服务定位器

  • “定位”一个现有的依赖项(服务)。尽管服务可以在解析期间创建,但对客户没有影响,因为:
  • 服务定位器的客户端不拥有依赖项的所有权。

工厂

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

抽象工厂

  • 与常规工厂相同,只是不同的部署可能使用抽象工厂的不同实现,允许在这些不同的部署中实例化不同的类型(您甚至可以在运行时更改抽象工厂的实现,但通常不是这样使用的。)
于 2012-02-22T22:05:02.737 回答
13

从我目前阅读的内容来看,我认为区别在于:

服务定位器模式

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

抽象工厂模式

  • 可能不支持注册——这取决于具体实现支持或不支持,并且可能不会暴露在抽象接口上
  • 通常对于特定的抽象类型有多个 get 方法
  • 本身不是具体的(虽然当然会有具体的实现)
于 2011-04-18T02:46:42.957 回答
2

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

然而读后

出现了一些严重的矛盾:

Seemann 说:“抽象工厂是泛型类型,Create 方法的返回类型是由工厂本身的类型决定的。也就是说,构造的类型只能返回单一类型的实例。”

尽管 Rober C. Martin 没有提到任何关于泛型类型的内容,而且,他书中的工厂示例允许创建多个类型对象的实例,使用键字符串作为 Factory.Make() 中的参数来区分它们。

Gamma 说抽象工厂的目的是“提供一个接口,用于创建相关或依赖对象的系列,而无需指定它们的具体类”。值得一提的是,Gamma Abstract Factory 示例违反了 Martin 所说的接口隔离原则 (ISP)。ISP 和 SOLID 通常是更现代的原则,或者为了简单起见,省略了。

Gamma 和 Martin 的作品先于 Seemann 的作品,所以我认为他应该遵循已经做出的定义。

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

然而,Seemann 和 Fowler 一致认为,Service Locator 需要一个配置步骤来注册一个具体类的实例,该实例将在以后请求此类对象时返回。Martin 或 Gamma 在他们对抽象工厂的定义中没有提到这个配置步骤。抽象工厂模式假设每次请求此类对象时都会实例化一个新对象。

结论

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

于 2015-02-08T02:51:10.297 回答
1

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

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

另一方面,服务定位器是具有通用方法的非通用接口。单个服务定位器的 Create 方法可以返回无数种类型的实例。

于 2016-03-06T12:35:52.897 回答
0

Martin Fowler 描述了服务定位器模式的几种实现,其中大部分是具体的类,通过static方法配置和调用。我认为我们可以忽略这些变化并专注于他使用依赖注入的最后一个示例,这是一种更现代的方法。我们可以将其与GoF 书中的抽象工厂模式进行比较。

抽象工厂的显着特征是一组固定的相关产品。相反,服务定位器具有无限的不相关产品集。这使得 Service Locator 更像是一个黑匣子,并可能导致对该模式的主要批评:它隐藏了 API 的依赖关系。当服务定位器被实现为动态注册表时,客户端可能会请求不存在的产品。这对于抽象工厂是不可能的。

考虑到抽象工厂和服务定位器之间的选择,前一种模式更可取。但这是一种错误的二分法,因为有更多选择。这两种模式都依赖于依赖注入,但没有它们,DI 会更好地工作。

注入是一种实现控制反转的机制。IoC 是依赖倒置的理想形式,因为它最大限度地减少了客户端的复杂性并提供了最高级别的抽象。服务定位器和抽象工厂是实现依赖反转而不反转控制的两种机制。从 IoC 是理想的角度来看,它们都是不可取的,而且它们都没有实现它。

有关 IoC 与 DI 的更多信息,请参阅:控制反转与依赖注入
有关抽象工厂和服务定位器陷阱的更多信息,请参阅:依赖注入代码气味

于 2021-09-01T01:58:10.390 回答