PHP 控制反轉(IoC) 和 依賴注入(DI)

dawson_liu發表於2020-06-10

簡單實現一個程式碼依賴:

<?php

class iocA
{
    public $b;
    public $c;

    public function A()
    {
        //TODO
    }

    public function Method()
    {
        $this->b = new iocB();
        $this->c = new iocC();

        $this->b->Method();
        $this->c->Method();
    }
}

class iocB
{
    public function C()
    {
        //TODO
    }

    public function Method()
    {
        echo 'b';
    }
}

class iocC
{
    public function C()
    {
        //TODO
    }

    public function Method()
    {
        //TODO
        echo 'c';
    }
}

$a = new iocA();
$a->Method();

上邊的程式碼實現了 iocA 類依賴 iocB 類和 iocC 類。
如果在開發過程中,需要對 iocB 類或者ioc C 類進行修改,,一旦涉及到函式名稱的改變,或者函式引數數量的變動,或者整個類結構的變化,我們也需要對 iocA 類進行調整,iocA 類的獨立性就喪失了,這在開發中和不方便,程式碼複雜,耦合度不盡人意,這樣會造成“牽一髮動全身”,解決這個問題就需要用到 控制翻轉(IOC)。

控制反轉(IOC)是一種思想,依賴注入(DI)是實施這種思想的方法。

依賴注入的實現

第一種:構造器注入

<?php

class iocA
{
    public $b;
    public $c;

    public function __construct($iocB, $iocC)
    {
        $this->b = $iocB;
        $this->c = $iocC;
    }

    public function Method()
    {
        $this->b->Method();
        $this->c->Method();
    }
}

class iocB
{
    public function C()
    {
        //TODO
    }

    public function Method()
    {
        echo 'b';
    }
}

class iocC
{
    public function C()
    {
        //TODO
    }

    public function Method()
    {
        //TODO
        echo 'c';
    }
}

$a = new iocA(new iocB(), new iocC());
$a->Method();

iocA 類的構造器依賴 iocB 類和 iocC 類,通過構造器的引數傳入,至少實現了一點,就是 iocB 類物件 b 和 iocC 類物件 c 的建立都移至了 iocA 類外,所以一旦 iocB 類和 iocC 類發生改動,iocA 類無需做修改,只要在相對應類裡改就可以了。

第二種:工廠模式注入

<?php

class Factory
{
    public function Factory()
    {
        //TODO
    }

    public function create($s)
    {
        switch ($s) {
            case 'B':
            {
                return new iocB();
                break;
            }
            case 'C':
            {
                return new iocC();
                break;
            }
            default:
            {
                return null;
                break;
            }
        }
    }
}

class iocA
{
    public $b;
    public $c;

    public function __construct()
    {
        //TODO
    }

    public function Method()
    {
        $factory = new Factory();
        $this->b = $factory->create('B');
        $this->c = $factory->create('C');

        $this->b->Method();
        $this->c->Method();
    }
}

class iocB
{
    public function C()
    {
        //TODO
    }

    public function Method()
    {
        echo 'b';
    }
}

class iocC
{
    public function C()
    {
        //TODO
    }

    public function Method()
    {
        //TODO
        echo 'c';
    }
}

$a = new iocA();
$a->Method();

其實已經解耦了一小部分,至少如果 iocB 類和 iocC 類的建構函式要是發生變化,

比如修改函式引數等,我們只需要改 Factory 類就可以了。

抽象不應該依賴於細節,細節應該依賴於抽象。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章