美文网首页
PHP控制反转(IOC)和依赖注入(DI)

PHP控制反转(IOC)和依赖注入(DI)

作者: 快乐的bug制造者 | 来源:发表于2018-03-18 16:13 被阅读125次

最近在做一个小程序支付的功能,支付流程就不说了。只是从官方提供的php代码来说,其实不简单,我也是看了好久才整明白!在我们调起统一支付接口之前,我们需要拼一堆数据如下此时它采用了依赖注入的思想:

<?php
        $input = new \WxPayUnifiedOrder();
        $input->SetBody("");
        $input->SetAttach("");
        $input->SetOut_trade_no($orderData['pay_order_no']);
        $input->SetTotal_fee($orderData['money']);
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetGoods_tag("");
        if($this->input['cv'] == 'weixin_app'){
            $input->SetNotify_url(WeixinpayConfig::WX_APP_NOTIFY_URL);
        }else{
            $input->SetNotify_url(WeixinpayConfig::MP_NOTIFY_URL);

        }

        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($openId);
        Tools::log(BaseConfig::CREATE_LOG.date('Ymd'), "input数据".json_encode($input->getValues()));

        $order = \WxPayApi::unifiedOrder($input,$timeOut = 6,$cv);
?>

其实我们可以看得出类WxPayApi是依赖于类WxPayUnifiedOrder,但是WxPayUnifiedOrder类中不管做任何修改,对于类WxPayApi都不需要做任何改变,就可以正常使用!这就是依赖注入,这样说理解起来可能费劲一些!写个简单的demo如下:

<?php
 
class A
{
    public $b;
    public $c;
    public function A()
    {
        //TODO
    }
    public function Method()
    {
        $this->b=new B();
        $this->c=new C();
         
        $this->b->Method();
        $this->c->Method();
         
        //TODO
    }
}
 
class B
{
    public function B()
    {
        //TODO
    }
    public function Method()
    {
        //TODO
        echo 'b';
    }
}
 
class C
{
    public function C()
    {
        //TODO
    }
    public function Method()
    {
        //TODO
        echo 'c';
    }
}
 
$a=new A();
$a->Method();
 
?>

上面代码,我们很容易理解一句话:

A类依赖B类和C类

也就是说,如果今后开发过程中,要对B类或者C类修改,一旦涉及函数改名,函数参数数量变动,甚至整个类结构的调整,我们也要对A类做出相应的调整,A类的独立性丧失了,这在开发过程中是很不方便的,也就是我们说的“牵一发动全身”,如果两个类是两个人分别写的,矛盾往往就在这个时候产生了。。。

万一真的要改动B类和C类,有没有办法,可以不去改动或者尽量少改动A类的代码呢?这里要用到控制反转。

控制反转(IOC)是一种思想,依赖注入(DI)是实施这种思想的方法。
第一种方法叫做:构造器注入(这种方法也不推荐用,但比不用要好):

class A
{
    public $b;
    public $c;
    public function A($b,$c)
    {
        $this->b=$b;
        $this->c=$c;
    }
    public function Method()
    {
        $this->b->Method();
        $this->c->Method();
    }
}

客户端类可以这样写:

$a=new A(new B(),new C());
$a->Method();

第二种方法叫做:工厂模式注入

class Factory
{
    public function Factory()
    {
        //TODO
    }
    public function create($s)
    {
        switch($s)
        {
            case 'B':
            {
                return new B();
                break;
            }
            case 'C':
            {
                return new C();
                break;
            }
            default:
            {
                return null;
                break;
            }
        }
    }
}

我们把A类改为如下写法:

class A
{
    public $b;
    public $c;
    public function A()
    {
        //TODO
    }
    public function Method()
    {
        $f=new Factory();
        $this->b=$f->create('B');
        $this->c=$f->create('C');
         
        $this->b->Method();
        $this->c->Method();
         
        //TODO
    }
}

其实已经解耦了一小部分,至少如果B类和C类的构造函数要是发生变化,比如修改函数参数等,我们只需要改Factory类就可以了。

把B类和C类中的方法再抽象出来,做一个接口:

interface IMethod
{
    public function Method();
}

这样,A类中的b变量和c变量就不再是一个具体的变量了,而是一个抽象类型的变量,不到运行那一刻,不知道他们的Method方式是怎么实现的。

class B implements IMethod
{
    public function B()
    {
        //TODO
    }
    public function Method()
    {
        //TODO
        echo 'b';
    }
}
 
class C implements IMethod
{
    public function C()
    {
        //TODO
    }
    public function Method()
    {
        //TODO
        echo 'c';
    }
}

总结几点:

1.我们把A类中的B类对象和C类对象的创建移至A类外

2.原本A类依赖B类和C类,现在变成了A依赖Factory,Factory依赖B和C。

相关文章

网友评论

      本文标题:PHP控制反转(IOC)和依赖注入(DI)

      本文链接:https://www.haomeiwen.com/subject/lcweqftx.html