English 中文(简体)
依赖性注射与服务定位模式有何区别?
原标题:What s the difference between the Dependency Injection and Service Locator patterns?
  • 时间:2009-10-13 01:15:19
  •  标签:

这两种模式似乎都像执行控制转移的原则。 这就是说,物体不应知道如何建造其附属地。

依赖性注射(DI)似乎使用一种构造或套体来“注射”其依赖性。

www.un.org/Depts/DGACM/index_spanish.htm 使用对应器注射的实例:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo(IBar bar)
  {
    this.bar = bar;
  }

  //...
}

服务定位器似乎使用“集装箱”,连接其附属设施,并给它带来 bar。

www.un.org/Depts/DGACM/index_spanish.htm 使用服务定位器的实例:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo()
  {
    this.bar = Container.Get<IBar>();
  }

  //...
}

由于我们的属地只是自己所为,这些属地更依赖,因此依此等等。 因此,控制集装箱(或DI集装箱)的转移产生。 实例:Cas 温莎、Ninject、结构图、春等

但是,一个国际奥委会/DI集装箱像一个服务定位器一样,看实际上。 把它称作DI集装箱是坏名吗? 国际奥委会/DI集装箱是否只是另一个 类型 的服务定位器? 我们主要在拥有许多属地时使用DI集装箱,这是否是微妙的?

问题回答

差异似乎很小,但即便与服务供应商一样,这一班子仍然负责建立其附属关系。 它只是利用服务地点这样做。 有了DI,这个班子就获得其附属条件。 它既不了解,也不照顾他们来自何处。 其中一个重要成果是,移民与发展研究所的例子更容易进行单位测试,因为你可以绕过其附属物体的安装。 如果你想要的话,你可以把两者结合起来——并注入服务地点(或工厂)。

当你使用服务定位器时,每一班都将依赖你的服务定位器。 依赖注射的情况并非如此。 通常只有在开始将抚养人送入某些主要阶层时,才有一次。 这一主要班级取决于在有完整的标书之前,能否重新注入其附属区。

比较好:rel=“noreferer” http://martinfowler.com/articles/injection.html

如果受抚养的注射器像服务站,这些班级直接指注射器,则可能不是依赖注射器,而是服务站。

服务定位器隐藏着依赖物——如果从定位器获得联系,你可以发现物体是否击中数据库(例如)。 依赖注射(至少是建筑注射)是明确的。

此外,服务定位器由于提供获得其他物体依赖性的全球途径而中断了计算。

it becomes difficult to specify the pre and post conditions for the client object s interface, because the workings of its implementation can be meddled with from outside.

如果有受抚养人注射,一旦确定物体受抚养人,他们就会控制物体本身。

<Martin Fowler states:

With service locator the application class asks for it explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class – hence the inversion of control.

简言之,服务定位器和依赖性注射只是实施依赖性转移原则。

重要原则是“在摘要上,而不是在判决上”。 这将使你的软件设计“相互结合”、“可扩展”、“灵活”。

你们能够利用最适合你们需要的人才。 对于一个具有巨大代码基的大型应用,你会更好地利用一个服务定位器,因为依赖性注射将需要对你的代码基数作更多的改动。

您可以检查这一职位:。 依赖性转移:服务定位或依赖性注射

也是经典的:rel=“noreferer” Martin Fowler

rel=“noretinger”>Designing Reusable Leveles by Ralph E. Johnson & Brianfoote

然而,打开我的眼睛的是:

一家使用建筑商DI的班子表示,需要满足一些需要。 如果该类人利用SL内部收回这些受扶养人,则消费法并不了解受扶养人。 表面上看上去可能更好,但了解任何明确依赖性实际上是有益的。 从建筑角度看,情况较好。 在进行测试时,你必须知道某类人是否需要某些依赖物,并召集利比里亚武装部队提供这些依赖物的适当假版本。 土库曼公司刚刚通过。 不是巨大的差异,而是存在。

DI和SL可以共同努力。 共同依赖点(例如环境、伐木等)的中央位置是有益的。 鉴于使用这种假肢的等级,你可以创建“真实”的构造者,接收假肢,以及从SL中提取并转至“真实”构造的违约(无参数)。

EDIT:当然,当你使用SL时,你正在对这个部分进行一些政变。 具有讽刺意味的是,这种功能的想法是鼓励抽象和减少政变。 这些关切是可以平衡的,这取决于你们需要多少地方使用《特别法》。 如如上所示,就在违约等级建筑商。

两者都是IoC的实施技术。 还有一些实施控制转移的其他模式:

  • Factory pattern
  • Service locator
  • DI (IoC) Container
  • Dependency injection (constructor injection, parameter injection (if not required), setter injection of interface injection) ...

服务定位器和DI集装箱似乎更为相似,两者都使用集装箱来界定依赖性,这为具体实施绘制了地图。

主要的区别是,依赖者是如何在服务定位器中找到的,客户代码要求依赖者,在DI集装箱中,我们使用集装箱制造所有物体,并作为建筑参数(或特性)注入依赖性。

在上周我们为微型信贷基金项目撰写的最新文件(我帮助建立微型信贷基金)的启发下添加一个理由。

一旦由可能数千个组成部分组成的评估,就难以确定任何具体组成部分能否得到正确处理。 我通过“正确证实”来表示,在这个例子中,基于<代码>。 Foo构成部分,一个编号为的事例,并可供查阅。

  • have its required dependencies,
  • not be involved in any invalid dependency cycles, and
  • in the case of MEF, be supplied with only one instance.

在第二例中,在施工者前往IoC集装箱收回其附属地时,你唯一能够测试的“<代码”的例子。 Foo将能够在上调,其实际操作时间为

这在试验时有各种各样的副作用,因为临时工作守则必然在试验中发挥作用。 由于真正的组合是我们需要测试的东西,而不是一些试验时间设置。

问题的根源是“Jon”已经指出的区别:通过建筑商的注射依赖性是宣示性的,而第二版则采用必须的服务定位模式。

一台IoC集装箱在经过仔细使用时,可以静态地分析贵方的运行时间配置,而不实际造成所涉部件的任何情况。 许多受欢迎的集装箱对此做了一些改动:Microsoft.Composition,即MEF目标版本。 NET 4.5 网络和大体字体,在维基文件中提供<编码>CompositionAssert样本。 采用这一方法,你可以写成这样的法典:

 // Whatever you use at runtime to configure the container
var container = CreateContainer();

CompositionAssert.CanExportSingle<Foo>(container);

(见

在检测时,通过核查你申请的Composition Fundamentals,你有可能发现某些错误,否则会在试验过程的晚些时候通过测试而消失。

我们希望,这是对这个以其他方式就这个专题提出的一整套答复的有趣补充。

我认为这两个工作是一起进行的。

依赖性注射意味着你将某些依赖性阶层/内部推向消费阶层(通常是建筑商)。 这通过一个接口使两个班子脱钩,意味着消费班可以与多种类型的“受威胁的依赖”项目合作。

服务提供者的作用是把执行工作结合起来。 您在方案启动时通过一些房间设置了服务站。 限制是将某种执行与某种具体抽象/接口联系起来的过程。 什么时候是为你们创造的。 (根据您的配置或boot)。 如果你没有实施依赖性注射,就很难使用一个服务点或IOC集装箱。

在简单构造之后,我更清楚地了解了服务定位器和DI集装箱之间的区别:

  • service Locator is used in the Consumer and it pulls services by ID from some sediment by direct Consumer s request

  • DI 集装箱位于外部,从某些储存和pushe向消费者提供服务(无论通过建筑或方法)。

然而,我们只能从具体的消费者使用的角度来谈论两者之间的区别。 当服务定位器和DI集装箱在成分根基中使用时,几乎是类似的。

注:我不确切回答问题。 但是,我认为,这可以帮助那些与-service Locator (anti-)pattern混淆起来的受抚养人。

我知道服务定位器(现在似乎被视为一种抗恩药剂)与依赖性注射模式之间的区别,并且能够理解每一种模式的具体实例,但我被一些例子混淆,这些例子显示,建筑商内部有一个服务定位器(假设我们再做建筑商注射)。

“服务定位器”常常既被用作一种模式的名称,又被用作指该模式中用来在不使用新操作器的情况下获取物体的物体(也指物)。 现在,在composition fundamental上也可使用同样的物体进行依赖注射,而混淆发生在哪里。

值得注意的是,你可能在DI建筑商中使用服务定位器物体,但你没有使用“服务定位器模式”。 如果把它称作IoC集装箱物体,那就不那么令人混淆了,因为你可能认为,这些集装箱基本上也做同样的事(如果我错了,那是正确的)。

无论把它称作服务定位器(或仅指定位器),还是作为IoC集装箱(或仅是集装箱),都与你所猜测不一样,他们都可能提到同样的抽象论(如果Im错的话,对我是正确的)。 仅仅称其为服务定位器就表明,有人正在使用服务定位器的抗爱国者以及依赖性注射方式。

IMHO将其命名为定位器,而不是定位或定位,有时还可能认为,某条中的服务定位器指的是服务定位器集装箱,而不是服务定位器(对应)主,特别是在有相关模式称为依赖性注射而不是依赖性注射器的情况下。

In this oversimplified case there is no difference and they can be used interchangeably. However, real world problems are not as simple. Just assume that the Bar class itself had another dependency named D. In that case your service locator wouldn t be able to resolve that dependency and you would have to instantiate it within the D class; because it is the responsibility of your classes to instantiate their dependencies. It would even get worse if the D class itself had other dependencies and in real-world situations it usually gets even more complicated than that. In such scenarios DI is a better solution than ServiceLocator.

页: 1 服从的客观准入模式 依附原则


依赖性注射是[静态/全球]物体进入模式

服务定位器是[动力]物体进入模式


如果您需要处理[dynamic structure],如[uiberry,或[设计的碎片],你可能需要服务定位器。

例:

  • createContext/useContext of React
  • provide/inject of Vue
  • Providers of angular

如果你只想从您的班子那里得到一例,don t care about the行踪: and the status of the instance in thatRank,你就应当使用DI。

例:

  • Annotation in C#/Java

当你不知道服务的实际提供人之前使用服务定位器。

当你知道自己是提供这一服务的法定集装箱时,即使用DI。


服务定位模式更像module level。 依赖性提供者,而DI是global level

如果有一个sub-module,即宣布依赖应由其提供的 父母-module提供的服务,而不是固定的解决类型(singleton/transient/static-copd)。

可以通过国际交易日志的 广域>喷射模式加以实施,而应用的模块结构/关系界定了范围。


个人建议:

  1. use DI wherever possible.
  2. use Service Locator if you have to deal with dynamic/runtime service resolvation in fractal structure.
  3. encapsulate the Service Locator as a scoped DI, for example: @inject({ scope: contextual })
  4. Locate the service by interface, instead of the class/constructor.

详细信息:https://learn.microsoft.com/zh-cn/dotnet/分/extensions/dependency-injection-guidelines# recommendations

依赖性注射与服务提供者之间的区别(如果有)是什么? 这两种模式都有利于执行依赖性转移原则。 服务定位器模式更容易在现有的编码数据库中使用,因为它使总体设计变得松散,同时又不强迫改变公共接口。 出于同样的原因,以服务定位器模式为基础的编码比基于依赖性注射的等值代码差。

依赖性注射模式表明了这一点,因为取决于某类(或某种方法)的签名将会有。 为此原因,由此形成的法典更清洁,更可读。

DI集装箱是服务定位器的superset。 它可以用于定位服务,额外能力为assembling (wiring) the injections of Depend





相关问题