角度依赖注入实现,为什么?

JRE*_*EAM 12 angular

如果有人说的话,请原谅我不理解这一点.

为什么Angpen实现的Dependency Injector通过a使用注射剂constructor

我习惯以DI各种方式看待.即使是一种静态方法也是有意义的(如果存在对不起我还没挖到那么深,我到目前为止已经进入了一周).

以这种方式使用它会不会更容易或更合乎逻辑,更类似于我们经常看到但仍然在构造函数中传递它的DI?

// Non-Angular Example
@Component({})
class FooComponent {
  public appState: AppState;

  constructor(DI: DependencyInjector) {
    this.appState = DI.get('AppState'); 
  }

  ngOnInit() {}
}
Run Code Online (Sandbox Code Playgroud)

Angular更像是这样,我不确定它是仅仅是为了冗长,还是有其他原因.

// Angular 2/4 Example 
@Component({})
class BarComponent {
  public appState: AppState;

  constructor(appState: AppState, 
              router: Router,
              etc: EtcSomething) {

  }
  ngOnInit() {}
Run Code Online (Sandbox Code Playgroud)

我知道谷歌已经想到了这一点,我只是想了解推理和/或好处.也许我醒来时想到了愚蠢的事情,这很明显,只是我的头脑,但我错过了.

我希望我所要求的是有道理的,我只是想知道为什么.

Igo*_*gor 9

以这种方式使用它会不会更容易或更合乎逻辑,更类似于我们经常看到但仍然在构造函数中传递它的DI?

示例中的模式图示实际上称为服务定位器模式.许多人认为这种模式是一种反模式.

服务定位器模式

好处

  • "服务定位器"可以充当简单的运行时链接器.这允许在运行时添加代码而无需重新编译应用程序,在某些情况下甚至无需重新启动它.
  • 应用程序可以通过有选择地添加和删除服务定位器中的项目来在运行时优化自身.例如,应用程序可以检测到它有一个更好的库来读取可用的JPG图像而不是默认图像,并相应地更改注册表.
  • 库或应用程序的大部分可以完全分开.它们之间的唯一联系就是注册表.

缺点

  • 放在注册表中的内容实际上是关于系统其余部分的黑盒子.这使得检测和恢复错误变得更加困难,并且可能使整个系统的可靠性降低.
  • 注册表必须是唯一的,这可能使其成为并发应用程序的瓶颈.
  • 注册表可能是一个严重的安全漏洞,因为它允许外人将代码注入应用程序.
  • 注册表隐藏了类的依赖项,在缺少依赖项时导致运行时错误而不是编译时错误.
  • 注册表使代码更难以维护(与使用依赖注入相反),因为不清楚何时引入重大更改.
  • 注册表使代码更难以测试,因为所有测试都需要与同一个全局服务定位器类交互以设置被测试类的伪依赖性.但是,通过使用单个服务定位器接口注入应用程序类可以轻松克服这个问题.

依赖注入

(目前)angular(以及其他框架)使用的(首选)模式.

好处

  • 依赖注入允许客户端灵活地进行配置.只修改了客户端的行为.客户端可以对支持客户期望的内部接口的任何事情采取行动.
  • 依赖注入可用于将系统的配置详细信息外部化为配置文件,从而允许在不重新编译的情况下重新配置系统.可以针对需要不同组件实现的不同情况编写单独的配置.这包括但不限于测试.
  • 因为依赖注入不需要对代码行为进行任何更改,所以它可以作为重构应用于遗留代码.结果是客户端更加独立,并且使用存根或模拟对象模拟其他未测试的对象,更容易单独进行单元测试.这种易测性通常是使用依赖注入时注意到的第一个好处.
  • 依赖注入允许客户端删除它需要使用的具体实现的所有知识.这有助于将客户端与设计更改和缺陷的影响隔离开来.它提高了可重用性,可测试性和可维护性.
  • 减少应用程序对象中的样板代码,因为初始化或设置依赖项的所有工作都由提供程序组件处理.
  • 依赖注入允许并发或独立开发.两个开发人员可以独立开发彼此使用的类,而只需要知道类将通过的接口.插件通常由第三方商店开发,甚至从不与创建使用插件的产品的开发人员交谈.
  • 依赖注入减少了类与其依赖关系之间的耦合.

缺点

  • 依赖注入创建客户端,要求配置细节由构造代码提供.当明显的默认值可用时,这可能很麻烦.
  • 依赖注入可能使代码难以跟踪(读取),因为它将行为与构造分开.这意味着开发人员必须引用更多文件来跟踪系统的执行情况.
  • 依赖注入通常需要更多的前期开发工作,因为人们不能在需要的时间和地点召唤出正确的东西,但必须要求它被注入,然后确保它已被注入.
  • 依赖注入迫使复杂性从类中移出并进入类之间的链接,这可能并不总是令人满意或易于管理.
  • 具有讽刺意味的是,依赖注入可以鼓励依赖于依赖注入框架.

您可以找到有关这些模式的文章,书籍,教程和其他信息.虽然这是一个偏好的问题,但是人们普遍认为依赖服务定位器模式的依赖注入.

关于这两者之间的差异,还有其他类似的问题,例如:依赖注入和服务定位器模式之间有什么区别?.

  • 对于任何明确指定的接口(而不仅仅是 DI)来说,以下说法不都是正确的吗?:“两个开发人员可以独立开发彼此使用的类,而只需要知道这些类将通过哪个接口进行通信。” (2认同)

Yer*_*kon 1

// Non-Angular Example

@Component({})
class FooComponent {
  public appState: AppState;

  constructor(DI: DependencyInjector) {
    this.appState = DI.get('AppState'); 
  }

  ngOnInit() {}
}
Run Code Online (Sandbox Code Playgroud)

您可以在构造函数中使用注入器并手动注入您需要的内容:

@Component({})
class FooComponent {
  public appState: AppState;

  constructor(private injector: Injector) {
    this.appState = injector.get(AppState); 
  }

  ngOnInit() {}
}
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,组件执行注入器的工作,这在大多数情况下是不合理的。