亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

【modernPHP專題(3)】依賴注入與服務(wù)容器

terro / 2695人閱讀

摘要:而依賴倒置原則的思想是,上層不應(yīng)該依賴下層,應(yīng)依賴接口。上面通過(guò)構(gòu)造函數(shù)注入對(duì)象的方式,就是最簡(jiǎn)單的依賴注入當(dāng)然注入不僅可以通過(guò)構(gòu)造函數(shù)注入,也可以通過(guò)屬性注入,上面你可以通過(guò)一個(gè)來(lái)動(dòng)態(tài)為這個(gè)屬性賦值。

依賴倒置和控制反轉(zhuǎn)是一種編程思想,而依賴注入就是通過(guò)服務(wù)容器實(shí)現(xiàn)這種面向接口或者是面向抽象編程的思想
概念理解 依賴倒置原則

依賴倒置是一種軟件設(shè)計(jì)思想,在傳統(tǒng)軟件中,上層代碼依賴于下層代碼,當(dāng)下層代碼有所改動(dòng)時(shí),上層代碼也要相應(yīng)進(jìn)行改動(dòng),因此維護(hù)成本較高。而依賴倒置原則的思想是,上層不應(yīng)該依賴下層,應(yīng)依賴接口。意為上層代碼定義接口,下層代碼實(shí)現(xiàn)該接口,從而使得下層依賴于上層接口,降低耦合度,提高系統(tǒng)彈性

控制反轉(zhuǎn)

當(dāng)調(diào)用者需要被調(diào)用者的協(xié)助時(shí),在傳統(tǒng)的程序設(shè)計(jì)過(guò)程中,通常由調(diào)用者來(lái)創(chuàng)建被調(diào)用者的實(shí)例,但在這里,創(chuàng)建被調(diào)用者實(shí)例的工作不再由調(diào)用者來(lái)完成,而是將被調(diào)用者的創(chuàng)建移到調(diào)用者的外部,從而反轉(zhuǎn)被調(diào)用者的創(chuàng)建,消除了調(diào)用者對(duì)被調(diào)用者創(chuàng)建的控制,因此稱為控制反轉(zhuǎn)。

要實(shí)現(xiàn)控制反轉(zhuǎn),通常的解決方案是將創(chuàng)建被調(diào)用者實(shí)例的工作交由 IoC 容器來(lái)完成,然后在調(diào)用者中注入被調(diào)用者(通過(guò)構(gòu)造器/方法注入實(shí)現(xiàn)),這樣我們就實(shí)現(xiàn)了調(diào)用者與被調(diào)用者的解耦,該過(guò)程被稱為依賴注入。

依賴注入不是目的,它是一系列工具和手段,最終的目的是幫助我們開發(fā)出松散耦合(loose coupled)、可維護(hù)、可測(cè)試的代碼和程序。這條原則的做法是大家熟知的面向接口,或者說(shuō)是面向抽象編程。

通俗的說(shuō),在調(diào)用一個(gè)對(duì)象的方法,首先要實(shí)例化對(duì)象之后。 而所謂的注入,就是一種工廠模式的升華。由一個(gè)更高級(jí)的工廠(容器),來(lái)完成對(duì)象實(shí)例化,實(shí)現(xiàn)調(diào)用者與被調(diào)用者的解耦
解決什么問(wèn)題 實(shí)現(xiàn)調(diào)用者與被調(diào)用者的解耦
[info] 所謂的上層代碼依賴于接口,就是業(yè)務(wù)邏輯的實(shí)現(xiàn)是跳過(guò)了具體對(duì)象的抽象行為。比如我們要對(duì)用戶發(fā)消息,可以通過(guò)郵件發(fā)送,也可以通過(guò)短信發(fā)送。上層代碼不用關(guān)注其用什么發(fā)送,只發(fā)送即可(適配器模式)
interface Mail
{
    public function send();
}

class Email implements Mail
{
    public function send()
    {
        echo "發(fā)送郵件" . PHP_EOL;
    }
}

class SmsMail implements Mail
{
    public function send()
    {
        echo "發(fā)送短信" . PHP_EOL;
    }
}

// 注冊(cè)容器
class Register
{
    private $_mailObj;

    // 構(gòu)造函數(shù)里面已經(jīng)約束了必須是實(shí)現(xiàn)了Mail接口的類的實(shí)例
    public function __construct(Mail $mailObj)
    {
        $this->_mailObj = $mailObj;
    }

    public function doRegister()
    {
        // 一定會(huì)有send方法
        $this->_mailObj->send();//發(fā)送信息
    }
}


$emailObj = new Email();
$smsObj = new SmsMail();

$reg = new Register($emailObj);
$reg->doRegister();//使用email發(fā)送

$reg = new Register($smsObj);
$reg->doRegister($smsObj);//使用短信發(fā)送

使用構(gòu)造函數(shù)注入的方法,使得它只依賴于發(fā)送短信的接口,只要實(shí)現(xiàn)其接口中的"send"方法,不管你什么方式發(fā)送都可以。上面通過(guò)構(gòu)造函數(shù)注入對(duì)象的方式,就是最簡(jiǎn)單的依賴注入;當(dāng)然"注入"不僅可以通過(guò)構(gòu)造函數(shù)注入,也可以通過(guò)屬性注入,上面你可以通過(guò)一個(gè)"setter"來(lái)動(dòng)態(tài)為"mailObj"這個(gè)屬性賦值。

通過(guò)php反射機(jī)制實(shí)現(xiàn)自動(dòng)注入

真實(shí)的dependency injection container會(huì)提供更多的特性,如

自動(dòng)綁定(Autowiring)或 自動(dòng)解析(Automatic Resolution)

注釋解析器(Annotations)

延遲注入(Lazy injection)

c = $c;
    }

    public function doSomething()
    {
        $this->c->doSomething();
        echo __METHOD__ , "我是周伯通B|";
    }
}

class A
{
    private $b;

    public function __construct(B $b)
    {
        $this->b = $b;
    }

    public function doSomething()
    {
        $this->b->doSomething();
        echo __METHOD__ , "我是周伯通A|";;
    }
}

class Container
{
    private $s = [];

    public function __set($k , $c)
    {
        $this->s[$k] = $c;
    }

    public function __get($k)
    {
        return $this->build($this->s[$k]);
    }

    /**
     * 自動(dòng)綁定(Autowiring)自動(dòng)解析(Automatic Resolution)
     * @param string $className
     * @return object
     * @throws Exception
     */
    public function build($className)
    {
        // 如果是匿名函數(shù)(Anonymous functions),也叫閉包函數(shù)(closures)
        if ($className instanceof Closure) {
            // 執(zhí)行閉包函數(shù),并將結(jié)果
            return $className($this);
        }

        if(!class_exists($className)){
            throw new Exception("{$className} class is not exists");
        }

        /** @var ReflectionClass $reflector */
        $reflector = new ReflectionClass($className);

        // 檢查類是否可實(shí)例化, 排除抽象類abstract和對(duì)象接口interface
        if (!$reflector->isInstantiable()) {
            throw new Exception("Can"t instantiate this.");
        }

        /** @var ReflectionMethod $constructor 獲取類的構(gòu)造函數(shù) */
        $constructor = $reflector->getConstructor();

        // 若無(wú)構(gòu)造函數(shù),直接實(shí)例化并返回, (注意! 此處退出遞歸1)
        if (is_null($constructor)) {
            return new $className;
        }

        // 取構(gòu)造函數(shù)參數(shù),通過(guò) ReflectionParameter 數(shù)組返回參數(shù)列表
        $parameters = $constructor->getParameters();
        // 遞歸解析構(gòu)造函數(shù)的參數(shù)
        $dependencies = $this->getDependencies($parameters);
        // 創(chuàng)建一個(gè)類的新實(shí)例,給出的參數(shù)將傳遞到類的構(gòu)造函數(shù)。
        return $reflector->newInstanceArgs($dependencies);
    }

    /**
     * @param array $parameters
     * @return array
     * @throws Exception
     */
    public function getDependencies($parameters)
    {
        $dependencies = [];
        /** @var ReflectionParameter $parameter */
        foreach ($parameters as $parameter) {
            /** @var ReflectionClass $dependency */
            $dependency = $parameter->getClass();
            if (is_null($dependency)) {
                // 是變量,有默認(rèn)值則設(shè)置默認(rèn)值 (注意,此處退出遞歸2)
                $dependencies[] = $this->resolveNonClass($parameter);
            } else {
                // 是一個(gè)類,遞歸解析
                $dependencies[] = $this->build($dependency->name);
            }
        }
        return $dependencies;
    }

    /**
     * @param ReflectionParameter $parameter
     * @return mixed
     * @throws Exception
     */
    public function resolveNonClass($parameter)
    {
        // 有默認(rèn)值則返回默認(rèn)值
        if ($parameter->isDefaultValueAvailable()) {
            return $parameter->getDefaultValue();
        }
        throw new Exception("I have no idea what to do here.");
    }
}


/*// example1
$container = new Container();
$container->b = "B";
$container->a = function ($container){
    return new A($container->b);
};

// 從容器中取得A
$model = $container->a;
// output: C::doSomething我是周伯通C|B::doSomething我是周伯通B|A::doSomething我是周伯通A|
// 實(shí)現(xiàn)依賴自動(dòng)注入
$model->doSomething();*/


// example2
$di = new Container();
$di->php7 = "A"; // 自動(dòng)注入classA
/** @var A $php7 */
$foo = $di->php7;

$foo->doSomething(); //C::doSomething我是周伯通C|B::doSomething我是周伯通B|A::doSomething我是周伯通A|

參考:

https://www.cnblogs.com/pains...
https://www.cnblogs.com/phppe...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/31380.html

相關(guān)文章

  • modernPHP專題(14)】?jī)?nèi)置的http服務(wù)

    摘要:起就在中內(nèi)置了服務(wù)器但只是提供開發(fā)測(cè)試使用,不推薦使用中生產(chǎn)環(huán)境中。因?yàn)檫@個(gè)服務(wù)器接受處理請(qǐng)求時(shí)順序執(zhí)行的,不能并發(fā)處理。這個(gè)內(nèi)置的服務(wù)器使用起來(lái)非常的方便,你只需要執(zhí)行下面的命令啟動(dòng)服務(wù)器然后就可以訪問(wèn)了。 PHP 5.4起就在CLI SAPI中內(nèi)置了web服務(wù)器,但只是提供開發(fā)測(cè)試使用,不推薦使用中生產(chǎn)環(huán)境中。因?yàn)檫@個(gè)服務(wù)器接受處理請(qǐng)求時(shí)順序執(zhí)行的,不能并發(fā)處理。 這個(gè)內(nèi)置的web...

    RancherLabs 評(píng)論0 收藏0
  • modernPHP專題(7)】生成器語(yǔ)法

    摘要:通過(guò)生成器來(lái)生成關(guān)聯(lián)數(shù)組下面每一行是用分號(hào)分割的字段組合,第一個(gè)字段將被用作鍵名。正常來(lái)說(shuō),產(chǎn)生的是一個(gè),它的成員變量與函數(shù)不存在別名引用關(guān)系。關(guān)鍵字在的版本,生成器允許從其他生成器,可迭代對(duì)象或數(shù)組通過(guò)關(guān)鍵字來(lái)生成對(duì)應(yīng)的值輸出 一般你在迭代一組數(shù)據(jù)的時(shí)候,需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù),假設(shè)數(shù)組很大,則會(huì)消耗很大性能,甚至造成內(nèi)存不足。 //Fatal error: Allowed memory ...

    jackwang 評(píng)論0 收藏0
  • modernPHP專題(1)】php7常用特性整理

    摘要:它使得在生產(chǎn)環(huán)境中啟用斷言為零成本,并且提供當(dāng)斷言失敗時(shí)拋出特定異常的能力。錯(cuò)誤和異常改變了大多數(shù)錯(cuò)誤的報(bào)告方式。不同于傳統(tǒng)的錯(cuò)誤報(bào)告機(jī)制,現(xiàn)在大多數(shù)錯(cuò)誤被作為異常拋出。 PHP7性能 7最大的亮點(diǎn),應(yīng)該就是性能提高了兩倍,某些測(cè)試環(huán)境下甚至提高到三到五倍,具體可以了解以下鏈接: PHP7 VS HHVM (WordPress) HHVM vs PHP 7 – The Competit...

    Render 評(píng)論0 收藏0
  • modernPHP專題(2)】反射機(jī)制Reflection

    摘要:簡(jiǎn)介是才有的新功能,它是用來(lái)導(dǎo)出或提取出關(guān)于類方法屬性參數(shù)等的詳細(xì)信息,包括注釋。 簡(jiǎn)介 PHP Reflection API是PHP5才有的新功能,它是用來(lái)導(dǎo)出或提取出關(guān)于類、方法、屬性、參數(shù)等的詳細(xì)信息,包括注釋。 class Reflection { } interface Reflector { } class ReflectionException extends Exce...

    mrli2016 評(píng)論0 收藏0
  • modernPHP專題(6)】類的延遲綁定(后期綁定)

    摘要:實(shí)例化對(duì)象里面的所在哪個(gè)類就返回哪個(gè)類。訪問(wèn)的是當(dāng)前類有點(diǎn)像因?yàn)槠涫抢^承了的方法,而調(diào)用的。由此可見(jiàn),他們的區(qū)別只有在繼承中才能體現(xiàn)出來(lái),如果沒(méi)有任何繼承,那么這兩者是沒(méi)有區(qū)別的。但如果是在靜態(tài)方法內(nèi)本類的話,最好還是用 以static::來(lái)調(diào)用,是在運(yùn)行的那個(gè)時(shí)刻才執(zhí)行綁定操作; 父類中有個(gè)方法是延遲綁定的,在子類::調(diào)用這個(gè)方法的時(shí)候它又回到調(diào)用的子類開始向上找; exampl...

    adam1q84 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<