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

資訊專欄INFORMATION COLUMN

PHP程序員如何理解IoC/DI

DataPipeline / 1698人閱讀

摘要:依賴注入容器管理應(yīng)用程序中的全局對(duì)象包括實(shí)例化處理依賴關(guān)系。為了解決這樣的問題,我們?cè)俅位氐饺肿?cè)表創(chuàng)建組件。參考文章程序員如何理解依賴注入容器補(bǔ)充很多代碼背后,都是某種哲學(xué)思想的體現(xiàn)。

思想

思想是解決問題的根本
思想必須轉(zhuǎn)換成習(xí)慣
構(gòu)建一套完整的思想體系是開發(fā)能力成熟的標(biāo)志
——《簡(jiǎn)單之美》(前言)

.

“成功的軟件項(xiàng)目就是那些提交產(chǎn)物達(dá)到或超出客戶的預(yù)期的項(xiàng)目,而且開發(fā)過程符合時(shí)間和費(fèi)用上的要求,結(jié)果在面對(duì)變化和調(diào)整時(shí)有彈性。”
——《面向?qū)ο蠓治雠c設(shè)計(jì)》(第3版)P.236

術(shù)語介紹

——引用《Spring 2.0 技術(shù)手冊(cè)》林信良

非侵入性 No intrusive

框架的目標(biāo)之一是非侵入性(No intrusive)

組件可以直接拿到另一個(gè)應(yīng)用或框架之中使用

增加組件的可重用性(Reusability)

容器(Container)

管理對(duì)象的生成、資源取得、銷毀等生命周期

建立對(duì)象與對(duì)象之間的依賴關(guān)系

啟動(dòng)容器后,所有對(duì)象直接取用,不用編寫任何一行代碼來產(chǎn)生對(duì)象,或是建立對(duì)象之間的依賴關(guān)系。

IoC

控制反轉(zhuǎn) Inversion of Control

依賴關(guān)系的轉(zhuǎn)移

依賴抽象而非實(shí)踐

DI

依賴注入 Dependency Injection

不必自己在代碼中維護(hù)對(duì)象的依賴

容器自動(dòng)根據(jù)配置,將依賴注入指定對(duì)象

AOP

Aspect-oriented programming

面向方面編程

無需修改任何一行程序代碼,將功能加入至原先的應(yīng)用程序中,也可以在不修改任何程序的情況下移除。

分層

表現(xiàn)層:提供服務(wù),顯示信息。
領(lǐng)域?qū)樱哼壿嫞到y(tǒng)中真正的核心。
數(shù)據(jù)源層:與數(shù)據(jù)庫、消息系統(tǒng)、事務(wù)管理器及其它軟件包通信。
——《企業(yè)應(yīng)用架構(gòu)模式》P.14

代碼演示IoC

假設(shè)應(yīng)用程序有儲(chǔ)存需求,若直接在高層的應(yīng)用程序中調(diào)用低層模塊API,導(dǎo)致應(yīng)用程序?qū)Φ蛯幽K產(chǎn)生依賴。

/**
 * 高層
 */
class Business
{
    private $writer;

    public function __construct()
    {
        $this->writer = new FloppyWriter();
    }

    public function save()
    {
        $this->writer->saveToFloppy();
    }
}

/**
 * 低層,軟盤存儲(chǔ)
 */
class FloppyWriter
{
    public function saveToFloppy()
    {
        echo __METHOD__;
    }
}

$biz = new Business();
$biz->save(); // FloppyWriter::saveToFloppy

假設(shè)程序要移植到另一個(gè)平臺(tái),而該平臺(tái)使用USB磁盤作為存儲(chǔ)介質(zhì),則這個(gè)程序無法直接重用,必須加以修改才行。本例由于低層變化導(dǎo)致高層也跟著變化,不好的設(shè)計(jì)。

正如前方提到的

控制反轉(zhuǎn) Inversion of Control
依賴關(guān)系的轉(zhuǎn)移
依賴抽象而非實(shí)踐

程序不應(yīng)該依賴于具體的實(shí)現(xiàn),而是要依賴抽像的接口。請(qǐng)看代碼演示

/**
 * 接口
 */
interface IDeviceWriter
{
    public function saveToDevice();
}

/**
 * 高層
 */
class Business
{
    /**
     * @var IDeviceWriter
     */
    private $writer;

    /**
     * @param IDeviceWriter $writer
     */
    public function setWriter($writer)
    {
        $this->writer = $writer;
    }

    public function save()
    {
        $this->writer->saveToDevice();
    }
}

/**
 * 低層,軟盤存儲(chǔ)
 */
class FloppyWriter implements IDeviceWriter
{

    public function saveToDevice()
    {
        echo __METHOD__;
    }
}

/**
 * 低層,USB盤存儲(chǔ)
 */
class UsbDiskWriter implements IDeviceWriter
{

    public function saveToDevice()
    {
        echo __METHOD__;
    }
}

$biz = new Business();
$biz->setWriter(new UsbDiskWriter());
$biz->save(); // UsbDiskWriter::saveToDevice

$biz->setWriter(new FloppyWriter());
$biz->save(); // FloppyWriter::saveToDevice

控制權(quán)從實(shí)際的FloppyWriter轉(zhuǎn)移到了抽象的IDeviceWriter接口上,讓Business依賴于IDeviceWriter接口,且FloppyWriter、UsbDiskWriter也依賴于IDeviceWriter接口。

這就是IoC,面對(duì)變化,高層不用修改一行代碼,不再依賴低層,而是依賴注入,這就引出了DI。

比較實(shí)用的注入方式有三種:

Setter injection 使用setter方法

Constructor injection 使用構(gòu)造函數(shù)

Property Injection 直接設(shè)置屬性

事實(shí)上不管有多少種方法,都是IoC思想的實(shí)現(xiàn)而已,上面的代碼演示的是Setter方式的注入。

依賴注入容器 Dependency Injection Container

管理應(yīng)用程序中的『全局』對(duì)象(包括實(shí)例化、處理依賴關(guān)系)。

可以延時(shí)加載對(duì)象(僅用到時(shí)才創(chuàng)建對(duì)象)。

促進(jìn)編寫可重用、可測(cè)試和松耦合的代碼。

理解了IoC和DI之后,就引發(fā)了另一個(gè)問題,引用Phalcon文檔描述如下:

如果這個(gè)組件有很多依賴, 我們需要?jiǎng)?chuàng)建多個(gè)參數(shù)的setter方法??來傳遞依賴關(guān)系,或者建立一個(gè)多個(gè)參數(shù)的構(gòu)造函數(shù)來傳遞它們,另外在使用組件前還要每次都創(chuàng)建依賴,這讓我們的代碼像這樣不易維護(hù)

//創(chuàng)建依賴實(shí)例或從注冊(cè)表中查找
$connection = new Connection();
$session = new Session();
$fileSystem = new FileSystem();
$filter = new Filter();
$selector = new Selector();

//把實(shí)例作為參數(shù)傳遞給構(gòu)造函數(shù)
$some = new SomeComponent($connection, $session, $fileSystem, $filter, $selector);

// ... 或者使用setter

$some->setConnection($connection);
$some->setSession($session);
$some->setFileSystem($fileSystem);
$some->setFilter($filter);
$some->setSelector($selector);

假設(shè)我們必須在應(yīng)用的不同地方使用和創(chuàng)建這些對(duì)象。如果當(dāng)你永遠(yuǎn)不需要任何依賴實(shí)例時(shí),你需要去刪掉構(gòu)造函數(shù)的參數(shù),或者去刪掉注入的setter。為了解決這樣的問題,我們?cè)俅位氐饺肿?cè)表創(chuàng)建組件。不管怎么樣,在創(chuàng)建對(duì)象之前,它增加了一個(gè)新的抽象層:

class SomeComponent
{

    // ...

    /**
     * Define a factory method to create SomeComponent instances injecting its dependencies
     */
    public static function factory()
    {

        $connection = new Connection();
        $session = new Session();
        $fileSystem = new FileSystem();
        $filter = new Filter();
        $selector = new Selector();

        return new self($connection, $session, $fileSystem, $filter, $selector);
    }

}

瞬間,我們又回到剛剛開始的問題了,我們?cè)俅蝿?chuàng)建依賴實(shí)例在組件內(nèi)部!我們可以繼續(xù)前進(jìn),找出一個(gè)每次能奏效的方法去解決這個(gè)問題。但似乎一次又一次,我們又回到了不實(shí)用的例子中。

一個(gè)實(shí)用和優(yōu)雅的解決方法,是為依賴實(shí)例提供一個(gè)容器。這個(gè)容器擔(dān)任全局的注冊(cè)表,就像我們剛才看到的那樣。使用依賴實(shí)例的容器作為一個(gè)橋梁來獲取依賴實(shí)例,使我們能夠降低我們的組件的復(fù)雜性:

class SomeComponent
{

    protected $_di;

    public function __construct($di)
    {
        $this->_di = $di;
    }

    public function someDbTask()
    {

        // 獲得數(shù)據(jù)庫連接實(shí)例
        // 總是返回一個(gè)新的連接
        $connection = $this->_di->get("db");

    }

    public function someOtherDbTask()
    {

        // 獲得共享連接實(shí)例
        // 每次請(qǐng)求都返回相同的連接實(shí)例
        $connection = $this->_di->getShared("db");

        // 這個(gè)方法也需要一個(gè)輸入過濾的依賴服務(wù)
        $filter = $this->_di->get("filter");

    }

}

$di = new PhalconDI();

//在容器中注冊(cè)一個(gè)db服務(wù)
$di->set("db", function() {
    return new Connection(array(
        "host" => "localhost",
        "username" => "root",
        "password" => "secret",
        "dbname" => "invo"
    ));
});

//在容器中注冊(cè)一個(gè)filter服務(wù)
$di->set("filter", function() {
    return new Filter();
});

//在容器中注冊(cè)一個(gè)session服務(wù)
$di->set("session", function() {
    return new Session();
});

//把傳遞服務(wù)的容器作為唯一參數(shù)傳遞給組件
$some = new SomeComponent($di);

$some->someTask();

這個(gè)組件現(xiàn)在可以很簡(jiǎn)單的獲取到它所需要的服務(wù),服務(wù)采用延遲加載的方式,只有在需要使用的時(shí)候才初始化,這也節(jié)省了服務(wù)器資源。這個(gè)組件現(xiàn)在是高度解耦。例如,我們可以替換掉創(chuàng)建連接的方式,它們的行為或它們的任何其他方面,也不會(huì)影響該組件。

參考文章

PHP程序員如何理解依賴注入容器(dependency injection container)

http://docs.phalconphp.com/zh/latest/reference/di.html

What is Dependency Injection? Fabien Potencier

Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler

補(bǔ)充

很多代碼背后,都是某種哲學(xué)思想的體現(xiàn)。

以下引用《面向模式的軟件架構(gòu)》卷1模式系統(tǒng)第六章模式與軟件架構(gòu)

軟件架構(gòu)支持技術(shù)(開發(fā)軟件時(shí)要遵循的基本原則)

抽象

封裝

信息隱藏

分離關(guān)注點(diǎn)

耦合與內(nèi)聚

充分、完整、簡(jiǎn)單

策略與實(shí)現(xiàn)分離

策略組件負(fù)責(zé)上下文相關(guān)決策,解讀信息的語義和含義,將眾多不同結(jié)果合并或選擇參數(shù)值

實(shí)現(xiàn)組件負(fù)責(zé)執(zhí)行定義完整的算法,不需要作出與上下文相關(guān)的決策。上下文和解釋是外部的,通常由傳遞給組件的參數(shù)提供。

接口與實(shí)現(xiàn)分離

接口部分定義了組件提供的功能以及如何使用該組件。組件的客戶端可以訪問該接口。

實(shí)現(xiàn)部分包含實(shí)現(xiàn)組件提供的功能的實(shí)際代碼,還可能包含僅供組件內(nèi)部使用的函數(shù)和數(shù)據(jù)結(jié)構(gòu)。組件的客戶端不能訪問其實(shí)現(xiàn)部分。

單個(gè)引用點(diǎn)

軟件系統(tǒng)中的任何元素都應(yīng)只聲明和定義一次,避免不一致性問題。
10. 分而治之

軟件架構(gòu)的非功能特性

可修改性

可維護(hù)性

可擴(kuò)展性

重組

可移植性

互操作性

與其它系統(tǒng)或環(huán)境交互

效率

可靠性

容錯(cuò):發(fā)生錯(cuò)誤時(shí)確保行為正確并自行修復(fù)

健壯性:對(duì)應(yīng)用程序進(jìn)行保護(hù),抵御錯(cuò)誤的使用方式和無效輸入,確保發(fā)生意外錯(cuò)誤時(shí)處于指定狀態(tài)。

可測(cè)試性

可重用性

通過重用開發(fā)軟件

開發(fā)軟件時(shí)考慮重用

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/20888.html

相關(guān)文章

  • PHP序員如何理解依賴注入容器(dependency injection container)

    摘要:代碼這就是控制反轉(zhuǎn)模式。是變量有默認(rèn)值則設(shè)置默認(rèn)值是一個(gè)類,遞歸解析有默認(rèn)值則返回默認(rèn)值從容器中取得以上代碼的原理參考官方文檔反射,具有完整的反射,添加了對(duì)類接口函數(shù)方法和擴(kuò)展進(jìn)行反向工程的能力。 PHP程序員如何理解依賴注入容器(dependency injection container) 背景知識(shí) 傳統(tǒng)的思路是應(yīng)用程序用到一個(gè)Foo類,就會(huì)創(chuàng)建Foo類并調(diào)用Foo類的方法,假如這...

    Coding01 評(píng)論0 收藏0
  • 聊一聊PHP的依賴注入(DI) 和 控制反轉(zhuǎn)(IoC)

    摘要:前言最近在使用框架,看了下他的源碼,發(fā)現(xiàn)有很多地方也用到了依賴注入控制反轉(zhuǎn),覺得有必要和大家簡(jiǎn)單聊一聊什么是依賴注入以及怎么使用它。概念依賴注入和控制反轉(zhuǎn)是對(duì)同一件事情的不同描述,從某個(gè)方面講,就是它們描述的角度不同。 前言 最近在使用ThinkPHP5框架,看了下他的源碼,發(fā)現(xiàn)有很多地方也用到了依賴注入(控制反轉(zhuǎn)),覺得有必要和大家簡(jiǎn)單聊一聊什么是依賴注入以及怎么使用它。 簡(jiǎn)介 I...

    sixgo 評(píng)論0 收藏0
  • PHP IOC/DI 容器 - 依賴自動(dòng)注入/依賴單例注入/依賴契約注入/參數(shù)關(guān)聯(lián)傳值

    摘要:標(biāo)量參數(shù)關(guān)聯(lián)傳值依賴是自動(dòng)解析注入的,剩余的標(biāo)量參數(shù)則可以通過關(guān)聯(lián)傳值,這樣比較靈活,沒必要把默認(rèn)值的參數(shù)放在函數(shù)參數(shù)最尾部。 更新:github(給個(gè)小星星呀) -- 2018-4-11:優(yōu)化服務(wù)綁定方法 ::bind 的類型檢查模式 借助 PHP 反射機(jī)制實(shí)現(xiàn)的一套 依賴自動(dòng)解析注入 的 IOC/DI 容器,可以作為 Web MVC 框架 的應(yīng)用容器 1、依賴的自動(dòng)注入:你只需要...

    Paul_King 評(píng)論0 收藏0
  • Spring 冬天來了,春天還遠(yuǎn)嗎

    摘要:當(dāng)你需要用到某個(gè)對(duì)象時(shí),就可以使用如下代碼從容器中獲取獲取容器獲取容器中的對(duì)象管理方式的所創(chuàng)建與存儲(chǔ)的對(duì)象,我們稱之為屬性注入方式管理注解方式屬性注入注解方式 好處 IoC / DI,方便解耦 AOP 面向切面編程 聲明式事務(wù) 方便程序測(cè)試 方便集成其他優(yōu)秀框架 IoC 與 DI IoC 與 DI 的關(guān)系 IoC控制反轉(zhuǎn):主要是指【創(chuàng)建對(duì)象】這件事交給Spring進(jìn)行處理,無需開發(fā)...

    ddongjian0000 評(píng)論0 收藏0
  • OOD、DIP、IOCDI、依賴注入容器(即 控制反轉(zhuǎn)容器,IOC Container)

    摘要:服務(wù)本省作為一個(gè)高層類,對(duì)外提供訪問,卻受制于提供具體服務(wù)的服務(wù)提供者定義的實(shí)現(xiàn),高層模塊依賴底層模塊實(shí)現(xiàn),違背了依賴倒置原則。遵循依賴倒置原則的例子場(chǎng)景同介紹中場(chǎng)景。 1. 名詞介紹 OOD,面向?qū)ο笤O(shè)計(jì) DIP,依賴倒置(軟件設(shè)計(jì)原則) IOC,控制反轉(zhuǎn)(軟件設(shè)計(jì)模式) DI,依賴注入 IOC Container,控制反轉(zhuǎn)容器,也是依賴注入容器 2. 組成部分 服務(wù)清單(功能...

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

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

0條評(píng)論

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