[PHP-DI] 理解依赖注入
理解依赖注入
依赖注入 和 依赖注入容器 是不同的:
- 依赖注入 (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 做一些事情
- Foo 调用 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 做一些事情
- Foo 调用 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] 理解依赖注入的更多相关文章
- 通过laravel理解IoC(控制反转)容器和DI(依赖注入)
原文地址: http://www.insp.top/learn-laravel-container ,转载务必保留来源,谢谢了! 容器,字面上理解就是装东西的东西.常见的变量.对象属性等都可以算是容器 ...
- 理解依赖注入(DI - Dependency Injection)
系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Contro ...
- 深度理解依赖注入(Dependence Injection)
前面的话:提到依赖注入,大家都会想到老马那篇经典的文章.其实,本文就是相当于对那篇文章的解读.所以,如果您对原文已经有了非常深刻的理解,完全不需要再看此文:但是,如果您和笔者一样,以前曾经看过,似乎看 ...
- [转]深度理解依赖注入(Dependence Injection)
http://www.cnblogs.com/xingyukun/archive/2007/10/20/931331.html 前面的话:提到依赖注入,大家都会想到老马那篇经典的文章.其实,本文就是相 ...
- 深入浅出理解依赖注入这种由外部负责其依赖需求的行为,我们可以称其为 “控制反转(IoC)”
原文地址: http://www.insp.top/learn-laravel-container ,转载务必保留来源,谢谢了! 这个组件现在可以很简单的获取到它所需要的服务,服务采用延迟加载的方式, ...
- 理解依赖注入 for Zend framework 2
依赖注入(Dependency Injection),也成为控制反转(Inversion of Control),一种设计模式,其目的是解除类之间的依赖关系. 假设我们需要举办一个Party,Part ...
- DI:依赖注入详解
DI(依赖注入) 依赖注入的理解: 一般写程序的时候service层都需要用到dao层,所以一般都是在service层里面new dao ,而现在利用依赖注入的方式,直接把dao给了service层 ...
- Spring——IOC(控制反转)与DI(依赖注入)
IOC与DI的理解及使用 控制反转IOC(Inversion of Control)是一种设计思想,DI(依赖注入)是实现IOC的一种方法.在没有IOC的程序中,我们使用面向对象编程,对象的创建于对象 ...
- 【转】理解依赖注入(IOC)和学习Unity
IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection).作用:将各层的对象以松耦合的方式组织在一起,解耦,各 ...
随机推荐
- asp.net:如何实现负载均衡方案讨论 (nginx+iis实现负载均衡)
5台阿里云服务器,ip地址分别为 ip地址 名字简称 操作系统 iis服务器 cpu 内存DDR3 机械硬盘 11 ...
- golang 字符串统计
golang内建只认utf8 如果传递的字符串里含有汉字什么的,最好使用 utf8.RuneCountInString() 统计 字符串统计几种方法: - 使用 bytes.Count() 统计- 使 ...
- camera-arm-RPI
这个属于先收藏着,知道有个开源的东西. luvcview是一个开源项目,专注于UVC摄像头的测试,只要您的摄像头支持UVC驱动,即可使用luvcview测试程序,如何知道自己的摄像头是不是支持UVC驱 ...
- linux 添加多个网段
1.在系统中添加网络配置文件脚本 # cd /etc/sysconfig/network-scripts # cp ifcfg-eth0 ifcfg-eth0:0 2.修改新添加的网络配置脚本文件如下 ...
- 《JavaScript设计模式与开发》笔记 6.高阶函数
1.函数作为参数传递 1.回调函数 2.Array.prototype.sort 2.函数作为返回值输出 1.判断数据的类型 3.高级函数的实现AOP 4.高阶函数的其他应用 1.currying 函 ...
- 【巷子】---redux---【react】
一.flux的缺陷 因为dispatcher和Store可以有多个互相管理起来特别麻烦 二.什么是redux 其实redux就是Flux的一种进阶实现.它是一个应用数据流框架,主要作用应用状态的管理 ...
- 无需AutoCAD,用C#生成DWG文件
是一个类库:Teigha.NET for .DWG 利用它就可以在无需安装AutoCAD软件的情况下,生成.读取DWG文件,适合那些导入导出的场合. Teigha曾用名OpenDWG .DWGdire ...
- sql中的STRFTIME
STRFTIME返回的是一个字符串 STRFTIME('%w',myTime) in ('1','2','4','5') 可以正确执行,而 STRFTIME('%w',myTime) in (1,2, ...
- spring AOP的学习
1.Spring常用的概念 Joinpoint(连接点): 所谓连接点是指那些被拦截到的点.在spring中,这些点指的是方法,因为spring只支持方法类型的连接点. Pointcut(切入点): ...
- Tomcat中Url中文乱码解决办法
引自:http://thoughtfly.iteye.com/blog/1533481 默认的tomcat容器如果直接使用get方式在url中传中文时,传到后台接收会是乱码. 乱码问题 原因: tom ...