php依赖注入,和工厂模式不同点。

依赖注入

说这个话题之前先讲一个比较高端的思想--'依赖倒置原则'

"依赖倒置是一种软件设计思想,在传统软件中,上层代码依赖于下层代码,当下层代码有所改动时,上层代码也要相应进行改动,因此维护成本较高。而依赖倒置原则的思想是,上层不应该依赖下层,应依赖接口。意为上层代码定义接口,下层代码实现该接口,从而使得下层依赖于上层接口,降低耦合度,提高系统弹性"

 

上面的解释有点虚,下面我们以实际代码来解释这个理论

比如有这么条需求,用户注册完成后要发送一封邮件,然后你有如下代码:

class Mail{
    public function send()
    {
        /*这里是如何发送邮件的代码*/
    }
}

然后又注册的类'Register.class.php'

class Register{
    private $_emailObj;

    public function doRegister()
    {
        /*这里是如何注册*/

        $this->_emailObj = new Mail();
        $this->_emailObj->send();//发送邮件
    }
}

然后开始注册

include 'Mail.class.php';
include 'Register.class.php';
$reg = new Register();
$reg->doRegister();

看起来事情很简单,你很快把这个功能上线了,看起来相安无事... xxx天过后,产品人员说发送邮件的不好,要使用发送短信的,然后你说这简单我把'Mail'类改下...

又过了几天,产品人员说发送短信费用太高,还是改用邮件的好...  此时心中一万个草泥马奔腾而过..

以上场景的问题在于,你每次不得不对'Mail'类进行修改,而且还得改Register类。代码复用性很低,高层过度依赖于底层。那么我们就考虑'依赖倒置原则',让底层继承高层制定的接口,高层依赖于接口。

  interface Mail
{
    public function send();
}

class Email implements Mail()
{
    public function send()
    {
        //发送Email
    }
}

class SmsMail implements Mail()
{
    public function send()
    {
        //发送短信
    }
}

PHP接口(interface)的特点

1、接口的方法必须是公开的。

2、接口的方法默认是抽象的,所以不在方法名前面加abstract。

3、接口可以定义常量,但不能定义成员属性,常量的定义和用法和类中常量一样。

4、类可以实现多个接口(相当于把多个功能集于一身,如手机实现了小灵通、MP3、MP4的功能)

5、接口也可以继承接口。


class Register
{
    private $_mailObj;

    public function __construct(Mail $mailObj)
    {
        $this->_mailObj = $mailObj;
    }

    public function doRegister()
    {
        /*这里是如何注册*/
        $this->_mailObj->send();//发送信息
    }
}

下面开始发送信息

/* 此处省略若干行 */
$reg = new Register();  //实例化
$emailObj = new Email();
$smsObj = new SmsMail();

$reg->doRegister($emailObj);//使用email发送
$reg->doRegister($smsObj);//使用短信发送
/* 你甚至可以发完邮件再发短信 */

  上面的代码解决了'Register'对信息发送类的依赖,使用构造函数注入的方法,使得它只依赖于发送短信的接口,只要实现其接口中的'send'方法,不管你怎么发送都可以。上例就使用了"注入"这个思想,就像注射器一样将一个类的实例注入到另一个类的实例中去,需要用什么就注入什么。当然"依赖倒置原则"也始终贯彻在里面。"注入"不仅可以通过构造函数注入,也可以通过属性注入,上面你可以可以通过一个"setter"来动态为"mailObj"这个属性赋值。

和工厂模式不同点

  依赖注入的想法和工厂模式很像。它们是软件结构控制反转(IoC)的两种实现。简单地说,它们是针对同一问题的两种解决方案。

虽然两种模式都是将对象的创建从应用的逻辑中分离,但是依赖注入比工程模式更清晰。通过依赖注入,你的类就是 POJO,它只知道依赖而不关心它们怎么获取。使用工厂模式,你的类需要通过工厂来获取依赖。因此,使用 DI 会比使用工厂模式更容易测试。

使用工厂时,您的代码仍然负责创建对象。通过DI,您将该职责外包给另一个类或框架,该框架与您的代码分开

下面就是工厂模式


<?php
class Factory {//创建一个基本的工厂类
    static public function fac($id){//创建一个返回对象实例的静态方法
        if(1 == $id){
            return new A();
        }elseif(2==$id){
            return new B();
        }elseif(3==$id){
            return new C();
        }else{
           return new D(); 
        } 
        
    }
}
 
interface FetchName {//创建一个接口 接口可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。接口是通过 interface 关键字来定义的,其中定义所有的方法都是空的。接口中定义的所有方法都必须是公有的。
    public function getname();
}
 
//implements 实现接口类
class A implements FetchName{  
    private $name = "AAAAA";
    public function getname(){ return $this->name; }
}
class B implements FetchName{
    private $name = "BBBBB";
    public function getname(){ return $this->name; }
}
 
class C implements FetchName{
    private $name = "CCCCC";
    public function getname(){ return $this->name; }
}
 
class D implements FetchName{
    private $name = "DDDDD";
    public function getname(){ return $this->name; }
}
 
 
$o = Factory::fac(6);//调用工厂类中的方法
if($o instanceof FetchName){  //instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例
  echo  $o->getname();//DDDDD
}
 
$p=Factory::fac(2);
echo $p->getname();//BBBBB

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值