国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

terro / 2612人閱讀

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

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

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

控制反轉(zhuǎn)

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

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

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

通俗的說,在調(diào)用一個對象的方法,首先要實例化對象之后。 而所謂的注入,就是一種工廠模式的升華。由一個更高級的工廠(容器),來完成對象實例化,實現(xiàn)調(diào)用者與被調(diào)用者的解耦
解決什么問題 實現(xiàn)調(diào)用者與被調(diào)用者的解耦
[info] 所謂的上層代碼依賴于接口,就是業(yè)務(wù)邏輯的實現(xiàn)是跳過了具體對象的抽象行為。比如我們要對用戶發(fā)消息,可以通過郵件發(fā)送,也可以通過短信發(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;
    }
}

// 注冊容器
class Register
{
    private $_mailObj;

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

    public function doRegister()
    {
        // 一定會有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ā)送短信的接口,只要實現(xiàn)其接口中的"send"方法,不管你什么方式發(fā)送都可以。上面通過構(gòu)造函數(shù)注入對象的方式,就是最簡單的依賴注入;當(dāng)然"注入"不僅可以通過構(gòu)造函數(shù)注入,也可以通過屬性注入,上面你可以通過一個"setter"來動態(tài)為"mailObj"這個屬性賦值。

通過php反射機制實現(xiàn)自動注入

真實的dependency injection container會提供更多的特性,如

自動綁定(Autowiring)或 自動解析(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]);
    }

    /**
     * 自動綁定(Autowiring)自動解析(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);

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

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

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

        // 取構(gòu)造函數(shù)參數(shù),通過 ReflectionParameter 數(shù)組返回參數(shù)列表
        $parameters = $constructor->getParameters();
        // 遞歸解析構(gòu)造函數(shù)的參數(shù)
        $dependencies = $this->getDependencies($parameters);
        // 創(chuàng)建一個類的新實例,給出的參數(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)) {
                // 是變量,有默認值則設(shè)置默認值 (注意,此處退出遞歸2)
                $dependencies[] = $this->resolveNonClass($parameter);
            } else {
                // 是一個類,遞歸解析
                $dependencies[] = $this->build($dependency->name);
            }
        }
        return $dependencies;
    }

    /**
     * @param ReflectionParameter $parameter
     * @return mixed
     * @throws Exception
     */
    public function resolveNonClass($parameter)
    {
        // 有默認值則返回默認值
        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|
// 實現(xiàn)依賴自動注入
$model->doSomething();*/


// example2
$di = new Container();
$di->php7 = "A"; // 自動注入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)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/31380.html

相關(guān)文章

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

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

    RancherLabs 評論0 收藏0
  • modernPHP專題(7)】生成器語法

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

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

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

    Render 評論0 收藏0
  • modernPHP專題(2)】反射機制Reflection

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

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

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

    adam1q84 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<