python ioc di_PHP的依赖注入(DI) 和 控制反转(IoC)
要想理解 PHP 依賴(lài)注入 和 控制反轉(zhuǎn) 兩個(gè)概念,就必須搞清楚如下的兩個(gè)問(wèn)題:DI —— Dependency Injection 依賴(lài)注入
IoC —— Inversion of Control 控制反轉(zhuǎn)
什么是依賴(lài)注入:
沒(méi)有你我就活不下去,那么,你就是我的依賴(lài)。 說(shuō)白了就是:不是我自身的,卻是我需要的,都是我所依賴(lài)的。一切需要外部提供的,都是需要進(jìn)行依賴(lài)注入的。
依賴(lài)注入舉例:class?Boy {
protected?$girl;
public?function?__construct(Girl?$girl) {
$this->girl =?$girl;
}
}
class?Girl {
...
}
$boy?=?new?Boy();??// Error; Boy must have girlfriend!
// 所以,必須要給他一個(gè)女朋友才行
$girl?=?new?Girl();
$boy?=?new?Boy($girl);?// Right! So Happy!
從上述代碼我們可以看到Boy強(qiáng)依賴(lài)Girl必須在構(gòu)造時(shí)注入Girl的實(shí)例才行。
那么為什么要有依賴(lài)注入這個(gè)概念,依賴(lài)注入到底解決了什么問(wèn)題?
我們將上述代碼修正一下我們初學(xué)時(shí)都寫(xiě)過(guò)的代碼:class?Boy {
protected?$girl;
public?function?__construct() {
$this->girl =?new?Girl();
}
}
這種方式與前面的方式有什么不同呢?
我們會(huì)發(fā)現(xiàn)Boy的女朋友被我們硬編碼到Boy的身體里去了。。。 每次Boy重生自己想換個(gè)類(lèi)型的女朋友都要把自己扒光才行。
某天Boy特別喜歡一個(gè)LoliGirl ,非常想讓她做自己的女朋友。。。怎么辦? 重生自己。。。扒開(kāi)自己。。。把Girl扔了。。。把 LoliGirl塞進(jìn)去?????class?LoliGirl {
}
class?Boy {
protected?$girl;
public?function?__construct() {
//? $this->girl = new Girl();? // sorry...
$this->girl =?new?LoliGirl();
}
}
某天 Boy迷戀上了御姐....Boy 好煩。。。
是不是感覺(jué)不太好?每次遇到真心相待的人卻要這么的折磨自己。。。
Boy說(shuō),我要變的強(qiáng)大一點(diǎn)。我不想被改來(lái)改去的!
好吧,我們讓Boy強(qiáng)大一點(diǎn):interface?Girl {
// Boy need knows that I have some abilities.
}
class?LoliGril implement Girl {
// I will implement Girl"s abilities.
}
class?Vixen implement Girl {
// Vixen definitely is a girl, do not doubt it.
}
class?Boy {
protected?$girl;
public?function?__construct(Girl?$girl) {
$this->girl =?$girl;
}
}
$loliGirl?=?new?LoliGirl();
$vixen?=?new?Vixen();
$boy?=?new?Boy($loliGirl);
$boy?=?new?Boy($vixen);
Boy 很高興,終于可以不用扒開(kāi)自己就可以體驗(yàn)不同的人生了。。。So Happy!
依賴(lài)注入方式
1、構(gòu)造器 注入<?php
class?Book {
private?$db_conn;
public?function?__construct($db_conn) {
$this->db_conn =?$db_conn;
}
}
2、setter 注入<?php
class?Book {
private?$db;
private?$file;
function?setdb($db) {
$this->db =?$db;
}
function?setfile($file) {
$this->file =?$file;
}
}
class?file {
}
class?db {
}
// ...
class?test {
$book?=?new?Book();
$book->setdb(new?db());
$book->setfile(new?file());
}
小結(jié):
因?yàn)榇蠖鄶?shù)應(yīng)用程序都是由兩個(gè)或者更多的類(lèi)通過(guò)彼此合作來(lái)實(shí)現(xiàn)業(yè)務(wù)邏輯,這使得每個(gè)對(duì)象都需要獲取與其合作的對(duì)象(也就是它所依賴(lài)的對(duì)象)的引用。如果這個(gè)獲取過(guò)程要靠自身實(shí)現(xiàn),那么將導(dǎo)致代碼高度耦合并且難以維護(hù)和調(diào)試。
控制反轉(zhuǎn) (Inversion Of Control, IOC)
控制反轉(zhuǎn) 是面向?qū)ο缶幊讨械囊环N設(shè)計(jì)原則,可以用來(lái)減低計(jì)算機(jī)代碼之間的耦合度。其中最常見(jiàn)的方式叫做 依賴(lài)注入(Dependency Injection, DI), 還有一種叫"依賴(lài)查找"(Dependency Lookup)。通過(guò)控制反轉(zhuǎn),對(duì)象在被創(chuàng)建的時(shí)候,由一個(gè)調(diào)控系統(tǒng)內(nèi)所有對(duì)象的外界實(shí)體,將其所依賴(lài)的對(duì)象的引用傳遞給它。也可以說(shuō),依賴(lài)被注入到對(duì)象中。<?php
class?Ioc {
protected?$db_conn;
public?static?function?make_book() {
$new_book?=?new?Book();
$new_book->set_db(self::$db_conn);
//...
//...
//其他的依賴(lài)注入
return?$new_book;
}
}
此時(shí),如果獲取一個(gè)book實(shí)例,只需要執(zhí)行$newone = Ioc::makebook();
以上是container的一個(gè)具體實(shí)例,最好還是不要把具體的某個(gè)依賴(lài)注入寫(xiě)成方法,采用registry注冊(cè),get獲取比較好<?php
/**
* 控制反轉(zhuǎn)類(lèi)
*/
class?Ioc {
/**
* @var array 注冊(cè)的依賴(lài)數(shù)組
*/
protected?static?$registry?=?array();
/**
* 添加一個(gè) resolve (匿名函數(shù))到 registry 數(shù)組中
*
* @param string? $name??? 依賴(lài)標(biāo)識(shí)
* @param Closure $resolve 一個(gè)匿名函數(shù),用來(lái)創(chuàng)建實(shí)例
* @return void
*/
public?static?function?register($name, Closure?$resolve) {
static::$registry[$name] =?$resolve;
}
/**
* 返回一個(gè)實(shí)例
*
* @param string $name 依賴(lài)的標(biāo)識(shí)
* @return mixed
* @throws Exception
*/
public?static?function?resolve($name) {
if?(static::registered($name)) {
$name?=?static::$registry[$name];
return?$name();
}
throw?new?Exception("Nothing registered with that name");
}
/**
* 查詢(xún)某個(gè)依賴(lài)實(shí)例是否存在
*
* @param string $name
* @return bool
*/
public?static?function?registered($name) {
return?array_key_exists($name,?static::$registry);
}
}
現(xiàn)在就可以通過(guò)如下方式來(lái)注冊(cè)和注入一個(gè)<?php
Ioc::register("book",?function?() {
$book?=?new?Book();
$book->setdb("db");
$book->setfile("file");
return?$book;
});
// 注入依賴(lài)
$book?= Ioc::resolve("book");
問(wèn)題匯總
1、參與者都有誰(shuí)?
答:一般有三方參與者,一個(gè)是某個(gè)對(duì)象;一個(gè)是IoC/DI的容器;另一個(gè)是某個(gè)對(duì)象的外部資源。又要名詞解釋一下,某個(gè)對(duì)象指的就是任意的、普通的Java對(duì)象; IoC/DI的容器簡(jiǎn)單點(diǎn)說(shuō)就是指用來(lái)實(shí)現(xiàn)IoC/DI功能的一個(gè)框架程序;對(duì)象的外部資源指的就是對(duì)象需要的,但是是從對(duì)象外部獲取的,都統(tǒng)稱(chēng)資源,比如:對(duì)象需要的其它對(duì)象、或者是對(duì)象需要的文件資源等等。
2、依賴(lài):誰(shuí)依賴(lài)于誰(shuí)?為什么會(huì)有依賴(lài)?
答:某個(gè)對(duì)象依賴(lài)于IoC/DI的容器。依賴(lài)是不可避免的,在一個(gè)項(xiàng)目中,各個(gè)類(lèi)之間有各種各樣的關(guān)系,不可能全部完全獨(dú)立,這就形成了依賴(lài)。傳統(tǒng)的開(kāi)發(fā)是使用其他類(lèi)時(shí)直接調(diào)用,這會(huì)形成強(qiáng)耦合,這是要避免的。依賴(lài)注入借用容器轉(zhuǎn)移了被依賴(lài)對(duì)象實(shí)現(xiàn)解耦。
3、注入:誰(shuí)注入于誰(shuí)?到底注入什么?
答:通過(guò)容器向?qū)ο笞⑷肫渌枰耐獠抠Y源
4、控制反轉(zhuǎn):誰(shuí)控制誰(shuí)?控制什么?為什么叫反轉(zhuǎn)?
答:IoC/DI的容器控制對(duì)象,主要是控制對(duì)象實(shí)例的創(chuàng)建。反轉(zhuǎn)是相對(duì)于正向而言的,那么什么算是正向的呢?考慮一下常規(guī)情況下的應(yīng)用程序,如果要在A里面使用C,你會(huì)怎么做呢?當(dāng)然是直接去創(chuàng)建C的對(duì)象,也就是說(shuō),是在A類(lèi)中主動(dòng)去獲取所需要的外部資源C,這種情況被稱(chēng)為正向的。那么什么是反向呢?就是A類(lèi)不再主動(dòng)去獲取C,而是被動(dòng)等待,等待IoC/DI的容器獲取一個(gè)C的實(shí)例,然后反向的注入到A類(lèi)中。
5、依賴(lài)注入和控制反轉(zhuǎn)是同一概念嗎?
答:從上面可以看出:依賴(lài)注入是從應(yīng)用程序的角度在描述,可以把依賴(lài)注入描述完整點(diǎn):應(yīng)用程序依賴(lài)容器創(chuàng)建并注入它所需要的外部資源;而控制反轉(zhuǎn)是從容器的角度在描述,描述完整點(diǎn):容器控制應(yīng)用程序,由容器反向的向應(yīng)用程序注入應(yīng)用程序所需要的外部資源。
參考:
Laravel 中的 依賴(lài)注入 與 控制反轉(zhuǎn)
總結(jié)
以上是生活随笔為你收集整理的python ioc di_PHP的依赖注入(DI) 和 控制反转(IoC)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: u8 和 char如何转化_如何编写高效
- 下一篇: php版本最低要求:5.4_Zabbix