深入理解Laravel容器概念,DI依赖注入,IOC控制反转
IOC - 控制反转
DI - 依赖注入
这两个存在的目的都是为了解耦!
解耦可以理解为,原本紧密结合的两个磁铁,现在我们在他们中间加一层木板,强行将他们分开,却不影响他们原有的功能于磁性。
所谓依赖就是 Class A 对于功能function a() 的实现需要依赖于class B
而注入就是在Class A实现功能 function a() 时,直接将class B注入到A
举个例子,小明去买华为手机 买手机依赖华为
代码实现 :
class Huawei{
public $goods = [
'phone' => '手机:Mata30',
'computer' => '笔记本:Mata12'
];
}
class Persion{
public $huawei;
public $name;
//买手机依赖华为商城
public function __construct($name){
$this->huawei = new Huawei();
$this->name = $name;
}
public function buy($goodName){
// 先查看华为有什么商品
$goods = $this->huawei->goods;
$str = '华为商城有:'.implode(',',$goods);
echo $str.'</br>';
// 购买商品
$this->account($goodName);
}
// 商品结算
public function account($goodName)
{
$goods = $this->huawei->goods;
$good = $goods[$goodName];
echo $this->name.'购买了商品'.$good;
}
}
$xiaoming = new Persion('Xiaoming');
$xiaoming->buy('phone');
输出结果:
华为商城有:手机:Mata30,笔记本:Mata12
Xiaoming购买了商品手机:Mata30
乍看一眼还是没问题,但是如果小明突然想去小米买手机。这时候你就得改里面的构造方法。每次有需求都要改构造方法,这样的是非常糟糕的体验。
这时候就需要控制反转IOC
通俗点说,控制反转就是将new Huawei() 这个操作由 Person 类去决定,即在构造方法中传递参数,决定去华为还是小米买手机;
class Persion{
public $huawei;
public $name;
//买手机依赖华为商城
public function __construct($business,$name){
$this->huawei = new $business();
$this->name = $name;
}
}
所谓服务提供者就是为项目提供各种服务的
他主要做两个工作:
1.将服务实例类注册到服务容器中
2.自己会执行boot引导方法,去加载自己这个服务需要的一些东西
下面我以淘宝商城为例,实现降了N级别的Laravel IOC容器。
淘宝可以称为一个IOC容器,有客户和商家两种类型。
商家、客户都要注册进淘宝。
客户再获取商家的实例购买商家的产品。
下面代码实现:
// 客户类
class Customers{
//顾客姓名
private $name;
//创建对象时创建人名
public function __construct($name)
{
$this->name = $name;
}
// 获取客户实例类的时候会执行的方法
public function boot()
{
}
//购买商品方法
// Huawei 即依赖,通过注入的方式注入到$huawei中
public function buy(HuaWei $huawei,$goodName)
{
$str = '欢迎'.$this->name.'来到华为商城查看商品,我们的商品有:';
foreach ($huawei->goods as $good)
{
$str .= $good.',';
}
echo rtrim($str,',').'</br>';
$this->account($huawei,$goodName);
}
//商品结算方法
public function account(HuaWei $huaWei,$goodName)
{
$goods = $huaWei->goods;
$good = $goods[$goodName];
echo $this->name.'购买了华为产品:'.$good;
}
}
//华为商家类
class HuaWei{
//华为商品
public $goods;
//服务引导方法,上架商品
public function boot()
{
$this->goods = [
'phone' => '手机:Mata30',
'computer' => '笔记本:Mata12'
];
}
}
// 淘宝即IOC容器
class TaoBao
{
//存放各种商家
private $shangjia = [];
//存放各种客户
private $customer = [];
//往淘宝注册商家 参数1 商家名字, 参数2 闭包函数 商家实例
public function register($name,$bibao)
{
$this->shangjia[$name] = $bibao;
}
// 通过商家名字商家实例
public function getShangjia($name)
{
//执行闭包函数获取商家实例
$object = ($this->shangjia[$name])();
$object->boot();
return $object;
}
//客户在淘宝登录 参数1 用户别名 参数2 闭包函数,客户实例
public function login($name,$bibao){
$this->customer[$name] = $bibao;
}
public function getCunstomer($name)
{
//执行闭包函数获取客户实例
return ($this->customer[$name])();
}
}
//创建出淘宝平台IOC容器
$taobao = new TaoBao();
//华为商城入驻淘宝
$taobao->register('huawei',function (){
return new HuaWei() ;
});
//用户小明登录淘宝
$taobao->login('xiaoming',function (){
return new Customers('小明');
});
//用户阿三登录淘宝
$taobao->login('asan',function (){
return new Customers('阿三');
});
//获取登录人小明的实例
$xiaoming = $taobao->getCunstomer('xiaoming');
//获取华为实例
$huawei = $taobao->getShangjia('huawei');
//小明买华为手机
$xiaoming->buy($huawei,'phone');
可以看得出,IOC的本质就是操作数组。
当然Laravel 不是简单的通过 new 去获取注册的实例。而是通过反射的机制,获取类的构造方法,需要的参数等。然后再实例出对象。这个大家可以自己百度研究,实现过程比较复杂。
以上就是我对Laravel 容器的概念。