Service Locator模式与Abstract Factory模式有什么不同?

乍看之下,服务定位器模式看起来与抽象工厂模式相同。 他们似乎有相同的用途(你查询他们接收抽象服务的实例),他们都已经提到,当我读到dependency injection。

但是, 我已经将Service Locator模式描述为一个糟糕的主意 ,但是至less在一个主要的Dependency Injection框架中直接支持Abstract Factory模式 。

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

我在调查这些模式时偶然发现了同样的问题。 我认为服务定位器和工厂之间可能存在主要的差异(无论是否抽象):

服务定位器

  • “定位”一个现有的依赖项(服务)。 尽pipe服务可能在解决过程中创build,但对客户来说并不重要,因为:
  • 服务定位器的客户端不承担依赖关系的所有权

  • 创build一个依赖项的新实例
  • 工厂的客户拥有相关的所有权

抽象工厂

  • 除了不同的部署可能会使用抽象工厂的不同实现,允许在不同的部署中实例化不同的types(甚至可以在运行时更改抽象工厂的实现,但这通常不是如何使用的),它与常规Factory相同。

从我目前阅读的内容来看,我认为不同的是:

服务定位器模式

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

抽象工厂模式

  • 可能不支持注册 – 这是由具体的实现来支持,还是不支持,并且可能不会暴露在抽象接口上
  • 通常对于特定的抽象types有多个get方法
  • 本身不具体(虽然当然会有具体的实现)

其实这两种模式之间有明显的分离。 众所周知,两种模式都用于避免具体types的依赖。

但是在阅读之后

一些严重的矛盾出现了:

Seemann说:“抽象工厂是一个genericstypes,Create方法的返回types是由工厂本身的types决定的,换句话说,构造types只能返回单一types的实例。

虽然罗伯特·C·马丁没有提到任何关于genericstypes,而且他的书中的工厂例子允许创build多个types的对象的实例使用一个键string作为Factory.Make()中的参数来区分它们。

Gamma表示,抽象工厂的意图是“提供创build相关或依赖对象的家族的界面,而不指定具体的类”。 值得一提的是,Gamma抽象工厂的例子违反了Martin所说的接口隔离原则(ISP)。 一般而言,ISP和SOLID是更现代化的原则,或者为了简单起见,省略。

伽马和马丁的作品先于西曼的作品,所以我觉得他应该遵循已经定义的定义。

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

然而,Seemann和Fowler同意,服务定位器需要一个configuration步骤来注册一个混凝土类的实例,这个实例是当这种types的对象被请求时将被返回的东西。 Martin或Gamma在Abstract Factory的定义中没有提到这个configuration步骤。 抽象工厂模式假设一个新对象被实例化,每当这种对象被请求。

结论

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

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

Abstract Factory是一个genericstypes,Create方法的返回types是由工厂本身的types决定的。 换句话说,构造types只能返回单一types的实例。

另一方面,服务定位器是一个通用方法的非generics接口。 单个Service Locator的Create方法可以返回无数个types的实例。