理解依赖注入

依赖注入依赖注入容器 是不同的:

  • 依赖注入 (Dependency injection) 是编写更好代码的一种方法
  • 容器 (Container) 是帮助注入依赖关系的工具

你不需要一个容器来执行依赖注入,但是一个容器可以帮助你。

PHP-DI就是这样做的:使依赖注入更加实用。

理论

经典的PHP代码

下面是使用DI的代码大致工作的方式:

  • 应用程序需要 Foo(例如一个控制器),所以:
  • 应用程序创建 Foo
  • 应用程序调用 Foo
    • Foo 需要 Bar(例如一个服务),所以:
    • Foo 创建 Bar
    • Foo 调用 Bar
      • Bar 需要 Bim(一个服务,一个仓库……),所以:
      • Bar 创建 Bim
      • Bar 做一些事情

使用依赖注入 (Dependency injection)

下面是使用DI的代码大致工作的方式:

  • 应用程序需要 Foo ,它需要 Bar,它需要Bim,所以:
  • 应用程序创建 Bim
  • 应用程序创建 Bar 并给它 Bim
  • 应用程序创建 Foo 并给它 Bar
  • 应用程序调用 Foo
    • Foo 调用 Bar

      • Bar 做一些事情

这是控制反转的模式,被调用者和调用者之间的依赖性控制是相反的

最主要的优点是:在调用链顶部的那个总是。你可以控制所有依赖项,并完全控制您的应用程序的工作方式,你可以用另一个(例如你创建的一个)来替换依赖项。

例如,如果库X使用 Logger Y,而你想让它使用 Logger Z 呢?有了依赖注入,你就不需要更改库X的代码了。

使用容器 (Container)

那么,使用PHP-DI的代码是如何工作的:

  • 应用程序需要 Foo,所以:
  • 应用程序从 Container 获取 Foo,所以:
    • Container 创建 Bim
    • Container 创建 Bar 并给它 Bim
    • Container 创建 Foo 并给它 Bar
  • 应用程序调用 Foo
    • Foo 调用 Bar

      • Bar 做一些事情

简而言之,容器包含了创建和注入依赖的所有工作

In short, the container takes away all the work of creating and injecting dependencies.

用一个例子来理解

这是一个真实的例子,比较了一个经典的实现(使用new或单例)和使用依赖注入。

没有依赖注入

假设你有:

class GoogleMaps
{
public function getCoordinatesFromAddress($address) {
// calls Google Maps webservice
}
}
class OpenStreetMap
{
public function getCoordinatesFromAddress($address) {
// calls OpenStreetMap webservice
}
}

经典的做法是:

class StoreService
{
public function getStoreCoordinates($store) {
$geolocationService = new GoogleMaps();
// or $geolocationService = GoogleMaps::getInstance() if you use singletons return $geolocationService->getCoordinatesFromAddress($store->getAddress());
}
}

现在我们想使用OpenStreetMap而不是GoogleMaps,我们该怎么做?

我们必须更改StoreService的代码,以及所有其他使用GoogleMaps的类。

如果没有依赖注入,你的类与它们的依赖紧耦合。

使用依赖注入

StoreService 现在使用依赖注入:

class StoreService {
private $geolocationService; public function __construct(GeolocationService $geolocationService) {
$this->geolocationService = $geolocationService;
} public function getStoreCoordinates($store) {
return $this->geolocationService->getCoordinatesFromAddress($store->getAddress());
}
}

服务是使用接口 (Interface) 定义的:

interface GeolocationService {
public function getCoordinatesFromAddress($address);
} class GoogleMaps implements GeolocationService { ... class OpenStreetMap implements GeolocationService { ...

现在,StoreService的用户可以决定使用哪个实现。 它可以随时改变,不必重写StoreService

StoreService不再与它的依赖紧耦合。

The StoreService is no longer tightly coupled to its dependency.

使用 PHP-DI

你可能会发现依赖注入会带来一个缺点:你现在必须处理注入依赖关系。

这就是容器(Container),特别是PHP-DI可以帮助你的地方。

而不是写:

$geolocationService = new GoogleMaps();
$storeService = new StoreService($geolocationService);

你可以写:

$storeService = $container->get('StoreService');

并配置哪个GeolocationService PHP-DI应该通过配置自动注入到StoreService中:

$container->set('GeolocationService', \DI\create('GoogleMaps'));

如果您改变主意,现在只需要改变一行配置。

感兴趣吗? 继续阅读开始使用PHP-DI指南!

参考

p.s. 看到PHP-DI没有中文文档,第一次对着机翻瞎翻译,如有疏漏敬请指正。

[PHP-DI] 理解依赖注入的更多相关文章

  1. 通过laravel理解IoC(控制反转)容器和DI(依赖注入)

    原文地址: http://www.insp.top/learn-laravel-container ,转载务必保留来源,谢谢了! 容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器 ...

  2. 理解依赖注入(DI - Dependency Injection)

    系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Contro ...

  3. 深度理解依赖注入(Dependence Injection)

    前面的话:提到依赖注入,大家都会想到老马那篇经典的文章.其实,本文就是相当于对那篇文章的解读.所以,如果您对原文已经有了非常深刻的理解,完全不需要再看此文:但是,如果您和笔者一样,以前曾经看过,似乎看 ...

  4. [转]深度理解依赖注入(Dependence Injection)

    http://www.cnblogs.com/xingyukun/archive/2007/10/20/931331.html 前面的话:提到依赖注入,大家都会想到老马那篇经典的文章.其实,本文就是相 ...

  5. 深入浅出理解依赖注入这种由外部负责其依赖需求的行为,我们可以称其为 “控制反转(IoC)”

    原文地址: http://www.insp.top/learn-laravel-container ,转载务必保留来源,谢谢了! 这个组件现在可以很简单的获取到它所需要的服务,服务采用延迟加载的方式, ...

  6. 理解依赖注入 for Zend framework 2

    依赖注入(Dependency Injection),也成为控制反转(Inversion of Control),一种设计模式,其目的是解除类之间的依赖关系. 假设我们需要举办一个Party,Part ...

  7. DI:依赖注入详解

    DI(依赖注入) 依赖注入的理解: 一般写程序的时候service层都需要用到dao层,所以一般都是在service层里面new  dao ,而现在利用依赖注入的方式,直接把dao给了service层 ...

  8. Spring——IOC(控制反转)与DI(依赖注入)

    IOC与DI的理解及使用 控制反转IOC(Inversion of Control)是一种设计思想,DI(依赖注入)是实现IOC的一种方法.在没有IOC的程序中,我们使用面向对象编程,对象的创建于对象 ...

  9. 【转】理解依赖注入(IOC)和学习Unity

    IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection).作用:将各层的对象以松耦合的方式组织在一起,解耦,各 ...

随机推荐

  1. Linux 命令自动补齐快捷键

    Linux 命令自动补齐快捷键 : TAB

  2. mysql update 将一个表某字段设为另一个表某字段的值

    表新添加了一个字段,毫无疑问是空值.所以想将另一个表的某个字段的值写入到修改的表中. sql语句不复杂,但还是记录一下,因为也查了一会,以后说不定还会用到. mysql> update cent ...

  3. position 分层固定在屏幕某位置

    很多网站我们看到在屏幕右下角有一个,返回顶部,始终在那儿,还有些网站顶部菜单栏永远也是固定的不动,就是通过今天学习的position来做的. 在style中加入 positon:fixed;top 0 ...

  4. Azure 认知服务 (3) 计算机视觉API - 分析图像,使用C#代码

    <Windows Azure Platform 系列文章目录> 在上一节中Azure 认知服务 (2) 计算机视觉API - 分析图像,笔者介绍了如何使用API测试控制台进行调试. 本章将 ...

  5. 跟着未名学Office - 高效工作Outlook

    目录 第一篇邮件与联系人    1 第一节    使用与技巧    1 第二节    高效    11 第二篇    事务助手    21 第一节    日程管理    21 第二节    任务    ...

  6. Mysql 性能优化5【重要】数据库结构优化

    数据库设计的步骤 我们大多使用mysql 设计三范式 设置时区  

  7. Restful API设计规范及实战【说的比较清楚了】

    Restful API设计规范及实战   Restful API的概念在此就不费口舌了,博友们网上查哈定义文章很多,直入正题吧: 首先抛出一个问题:判断id为 用户下,名称为 使命召唤14(COD14 ...

  8. js页面滚动时层智能浮动定位实现

    直接上代码 $.fn.smartFloat = function (className) { var position = function (element) { var top = element ...

  9. LibreOffice转换文档到pdf时中文乱码

    根据我的测试,LibreOffice转换文档到pdf乱码主要有三个方面的原因: 1.centos缺少中文字体 2.jdk缺少中文字体 3.LibreOffice缺少中文字体. 解决该问题需要将wind ...

  10. C++中的指针与引用的区别与联系

    引用与指针实质上都是间接地指代另一个变量,引用相当于该变量的外号或者小名,而指针实质上是指向该变量的地址进而操作该变量 区别1:指针的地址与该变量不同,但引用的地址与该变量相同相同 #include& ...