初学依赖注入
学习了依赖注入,做一个记录.
一.概念
- 依赖倒置原则( Dependence Inversion Principle ,缩写为 DIP ),一种软件设计原则,是一个抽象的概念.
- 控制反转( Inversion of Control ,缩写为 IoC ),DIP 的一种具体实现方式.
- 依赖注入( Dependency injection ,缩写为 DI ),IOC 的具体实现方式.
什么是反转?对应的什么是正转?依赖谁?依赖什么?注入谁?注入什么?一个日常生活的例子,可以解惑:
- 某人想开车,于是自己去造车,此时可以理解为控制正转,我想要车多大我就造多大,想要车是什么颜色就涂什么颜色.
- 最后发现造车太难,于是选择去经销商买一辆车,可以理解为控制反转,经销商只提供蓝色的车,我就只能买蓝色的车,我被经销商控制了,我依赖经销商给我注入车
结论就是,造车难,买车容易,在写程序的时候使用依赖注入可以更好的解耦
二.自己造车
<?php
class Car
{
//汽车可以跑,定义一个方法 run()
public function run(){
return '滴滴滴,车开了';
}
}
class Person
{
private $car = null;//保存某人的车,暂时还没车
public function drive(){
$this->car = new Car();//要开车先造车,造了一辆车保存在某人的 $car 里
return $this->car->run();//调用车的 run() 方法
}
}
$xiaoming = new Person();
echo $xiaoming->drive();//输出 滴滴滴,车开了
三.造车太难了(依赖注入)
<?php
class Car
{
//汽车可以跑,定义一个方法 run()
public function run()
{
return '滴滴滴,车开了';
}
}
class Person
{
private $car = null;//保存某人的车,暂时还没车
//new 某人的时候,就给他注入一辆车,通过 $a 传入构造方法,并保存在 $car 里
public function __construct($a)
{
$this->car = $a;
}
public function drive()
{
return $this->car->run();//调用车的 run() 方法
}
}
$car = new Car();//买一辆车
$xiaoming = new Person($car);//new 小明的时候,把刚才买的车注入
echo $xiaoming->drive();//输出 滴滴滴,车开了
万一new小明的时候,给他买了一架飞机,并注入,小明不会开飞机怎么办,通过类型限定解决这个问题
class Person
{
.
.
.
public function __construct(Car $a)// <----这里做类型限定,保证不会注入飞机,也不会注入火箭
{
$this->car = $a;
}
.
.
.
四.IoC 容器
在上例中,我们是手动的去 new
一辆车并注入给某人,现在用一个容器统一的去管理这些需要注入的类。
<?php
class Car
{
//汽车可以跑,定义一个方法 run()
public function run()
{
return '滴滴滴,车开了';
}
}
class Person
{
private $car = null;//保存某人的车,暂时还没车
//new 某人的时候,就给他注入一辆车,通过 $a 传入构造方法
public function __construct(Car $a)// <----这里做了类型限定
{
$this->car = $a;
}
public function drive()
{
return $this->car->run();//调用车的 run() 方法
}
}
//写一个简单的 IoC 容器类
class Container{
private static $objArr = [];//定义一个静态的空数组
public static function set($flag, Callable $func){
self::$objArr[$flag] = $func;//存入键值对,键是一个字符串,作为标识符,值是一个匿名函数
}
public static function get($flag){
$tmp = self::$objArr[$flag];//取出标识符对应的匿名函数,用$tmp临时保存一下
return $tmp();//在$tmp后名加上括号,表示执行这个函数,并返回
}
}
//下面这条语句执行完毕后,会在 $objArr 里存入一个键值对,键是 car ,值是这个匿名函数,该匿名函数返回的是创建 Car 对象的语句
Container::set('Car', function(){
return new Car();
});
//下面这条语句执行完毕后,会在 $objArr 里存入一个键值对,键是 person ,值是这个匿名函数,该匿名函数返回的是创建 Person 对象的语句
Container::set('Person', function(){
return new Person(Container::get('Car'));//直接去容器中取一辆车出来,并作为参数传给 Person 类的构造函数
});
$xiaomin = Container::get('Person');//直接去容器中取一个人出来,取名叫小明
echo $xiaomin->drive();//输出 滴滴滴,车开了
本作品采用《CC 协议》,转载必须注明作者和本文链接
感觉讲得很通俗易懂呀~~~哈哈,不过什么场景下用依赖注入会比较合适呢?自己造车那一段代码感觉是最浅显易懂的,用上了依赖注入之后感觉就不那么便于理解了
@kevin2011 其实,我这个理解只是最基本的,就好像还停留在理论阶段,要真的运用在实际项目中,还需要更深入的学习.至于说运用场景,可以在任何时候,只要你想达到解耦的目的,就可以用,可是实际上这样的代码是无法用的,它的作用仅仅是帮助理解概念,在学习第一本书的的时候,我们已经不知不觉用了依赖注入,比如在
app/Http/Controllers/UsersController.php
文件中写过这样一段代码:滴,老司机卡
讲的不错