摘要:為了更好的理解依賴注入和容器的概念,我們先設(shè)計一個場景。那么調(diào)用過程將變成以上就是一種依賴注入的示例。徹底解除了對能源類的依賴。到目前為止,基本上已實現(xiàn)了的依賴注入了。一個實用和優(yōu)雅的解決方法,是為依賴實例提供一個容器。
為了更好的理解依賴注入 (DI) 和 IOC 容器的概念,我們先設(shè)計一個場景?,F(xiàn)在你餓了,準(zhǔn)備要享用一個晚餐,那么你可能要做的事情有購買食材,烹飪食材,享用食物。
晚餐的類設(shè)計看起來應(yīng)該像是這樣的:
單拿 cookFood 這步來說,你可能還需要一種能源資源,以便將食材加熱,比方說,你選擇了燃?xì)?。那么燃?xì)獾念愒O(shè)計看起來應(yīng)該像是這樣的:
好了,現(xiàn)在可以用燃?xì)鈦砑訜崃恕?/p>
... class Dinner { ... public function cookFood() { $gas = new Gas(); $gas->fire(); } ... }為節(jié)省篇幅,以上代碼使用了 ‘…’ 來隱藏了部分代碼,以下文章情況類似。那么調(diào)用過程是這樣的:
$dinner = new IocDinner(); $dinner->cookFood();以上的設(shè)計就產(chǎn)生了依賴了,Dinner 依賴了 Gas ,這種依賴讓兩個類耦合在一起,這種設(shè)計的缺陷是明顯的。萬一燃?xì)庥霉饬四兀f一由天燃?xì)飧某擅簹饬四?,那樣子晚餐就泡湯了。在代碼看來就是,一旦 Gas 類在某些環(huán)境下不能運作了,一旦 Gas 要更改類名了,那么 Dinner 會很被動,況且每一次調(diào)用都要 new 實例化一次 Gas ,這很浪費系統(tǒng)資源。
IOC 全稱是 Inversion of Control,譯作控制反轉(zhuǎn)。像以上設(shè)計,Dinner 稱作主類, Gas 稱作次類, 次類的實例化由主類來控制,這種方式就是正向的控制,如果次類的實例化并不由主類來控制的話,大概就是控制反轉(zhuǎn)的意思了。
怎么解決這種強(qiáng)耦合關(guān)系?一種解決方式是使用工廠模式。
工廠模式
工廠模式很簡單,就是使用一個代理類來幫助你批量實例化“次類”。
Agent 類如下:Dinner 類如下:
... class Dinner { protected $energy; ... public function cookFood() { $this->energy = Agent::useEnergy(); $this->energy->fire(); } ... }如此,即可使 Dinner 不再直接依賴 Gas,而交由一個代理 Agent 來控制 energy 的創(chuàng)建。然而,Gas 依賴解除了,又帶來了 Agent 的依賴,雖然 Agent 的更改可能性不太,但誰能保證呢。
依賴注入 (DI)
在徹底解除依賴,必須要將次類的調(diào)用代碼從主類中移除才行,否則次類像更改類名這樣的改動都將牽動著所在所有依賴它的主類的代碼,所有依賴它的主類都要跟著改代碼,可謂牽一發(fā)而動全身。
一種依賴注入的方式就是,被依賴的對象通過參數(shù)從外部注入到類內(nèi)部。更改 Dinner 類如下:
... public function setEnergy($energy) { $this->energy = $energy; } public function cookFood() { $this->energy->fire(); } ...添加一個 setEnergy 方法來注入依賴的對象。那么調(diào)用過程將變成:
$dinner = new IocDinner(); $dinner->setEnergy(IocAgent::useEnergy()); $dinner->cookFood();以上就是一種依賴注入的示例。Dinner 徹底解除了對能源類的依賴。
但是新問題還會產(chǎn)生,cookFood 并不只依賴能源,可能還依賴廚具,調(diào)味料等。那么調(diào)用過程將會是這樣的:
$dinner->setEnergy(...); $dinner->setKitchen(...); $dinner->setSauce(...); $dinner->cookFood();每次都要調(diào)用很多 set 方法,這樣就更不科學(xué)了。與其這樣,干脆所有 set 方法都交給一個 TopAgent 做好了。
TopAgent 類如下:setEnergy(Agent::useEnergy()); $dinner->setKitchen(Agent::useKitchen()); $dinner->setSauce(Agent::useSauce()); return $dinner; } }這樣,調(diào)用過程就變得簡單了。
到目前為止,基本上已實現(xiàn)了 Dinner 的依賴注入了??烧J(rèn)真一看,瞬間,似乎又回到了最初的問題了,不,不是似乎,簡直就是了! Dinner 類是解除了外部類的依賴了,但它自己卻成了 TopAgent 的依賴類了,而 TopAgent 不正是最初的 Dinner 了嗎!繞了一大圈,原來還在原點,一次又一次,我們又回到了不實用的例子中來了。
一個實用和優(yōu)雅的解決方法,是為依賴實例提供一個容器。即是 IOC 容器。
IOC 容器
IOC 容器首先是一種類注冊器,其次它是一種更高級的依賴注入方式。它和工廠 Factory 其實性質(zhì)一樣,代理類,但實現(xiàn)機(jī)制不一樣。
IOC 容器的設(shè)計模式叫做注冊器模式。
Container 類如下:Agent 類再添加兩個方法:
... public static function bindContainer() { return new Container(); } public static function bindDinner(Container $container) { return new Dinner($container); } ...Dinner 類接受一個 Container 注入:
container = $container; } public function buyFood() { // } public function cookFood() { $this->container->get("energy")->fire(); } public function eatFood() { // } }于是,調(diào)用過程便可漂亮的寫成:
IocContainer::set("energy", function () { return IocAgent::useEnergy(); }); $dinner = IocAgent::bindDinner(IocAgent::bindContainer()); $dinner->cookFood();將容器 Container 注入到 Dinner 。并實現(xiàn)了所有類的完全解耦。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/31816.html
摘要:對象之間耦合度過高的系統(tǒng),必然會出現(xiàn)牽一發(fā)而動全身的情形??刂票环崔D(zhuǎn)之后,獲得依賴對象的過程由自身管理變?yōu)榱擞扇萜髦鲃幼⑷?。于是,他給控制反轉(zhuǎn)取了一個更合適的名字叫做依賴注入。 Spring還可以這么學(xué)--IoC(控制反轉(zhuǎn)) / DI(依賴注入)理解 聲明:文章的前三部分參考博文:https://www.cnblogs.com/Nouno...這篇文章首發(fā)是在我的個人微信訂閱號每天學(xué)編...
摘要:構(gòu)造函數(shù)注入通過調(diào)用類的構(gòu)造函數(shù),將接口實現(xiàn)類通過構(gòu)造函數(shù)變量傳入。而在中,其使用橫切技術(shù),將這類代碼從原屬的封裝對象中提取出來,封裝到一個可重用模塊中,稱為。 最近實習(xí)用到Spring的開發(fā)框架,但是之前沒有接觸過,因此希望利用網(wǎng)上的資源來學(xué)習(xí)以下。 Spring官方給出了非常全面的介紹,非常適合我這種完全的小白……在這一系列學(xué)習(xí)中,我閱讀的主要資源是5.1.2 Reference ...
摘要:依賴注入容器管理應(yīng)用程序中的全局對象包括實例化處理依賴關(guān)系。為了解決這樣的問題,我們再次回到全局注冊表創(chuàng)建組件。參考文章程序員如何理解依賴注入容器補(bǔ)充很多代碼背后,都是某種哲學(xué)思想的體現(xiàn)。 思想 思想是解決問題的根本思想必須轉(zhuǎn)換成習(xí)慣構(gòu)建一套完整的思想體系是開發(fā)能力成熟的標(biāo)志——《簡單之美》(前言) . 成功的軟件項目就是那些提交產(chǎn)物達(dá)到或超出客戶的預(yù)期的項目,而且開發(fā)過程符合時間和費...
摘要:引述最近看設(shè)計模式以及代碼,對于控制反轉(zhuǎn)以及依賴注入這些概念非常困惑,于是找了一些資料,以下是對于控制反轉(zhuǎn)的一下理解。其中最常見的方式叫做依賴注入,簡稱,還有一種方式叫依賴查找。在軟件工程中,依賴注入是種實現(xiàn)控制反轉(zhuǎn)用于解決依賴性設(shè)計模式。 引述 最近看設(shè)計模式以及l(fā)aravel代碼,對于控制反轉(zhuǎn)以及依賴注入這些概念非常困惑,于是找了一些資料,以下是對于控制反轉(zhuǎn)的一下理解。 概念 Io...
摘要:簡單來說,是一個輕量級的控制反轉(zhuǎn)和面向切面的容器框架。變成的支持提供面向切面編程,可以方便的實現(xiàn)對程序進(jìn)行權(quán)限攔截,運行監(jiān)控等功能。用于反射創(chuàng)建對象,默認(rèn)情況下調(diào)用無參構(gòu)造函數(shù)。指定對象的作用范圍。 1.Spring介紹 1.1 Spring概述 Spring是一個開源框架,Spring是于2003 年興起的一個輕量級的Java 開發(fā)框架,由Rod Johnson 在其著作Expert...
閱讀 2129·2023-04-25 21:11
閱讀 2994·2021-09-30 09:47
閱讀 2299·2021-09-24 09:48
閱讀 4477·2021-08-23 09:43
閱讀 927·2019-08-30 15:54
閱讀 590·2019-08-28 18:01
閱讀 1431·2019-08-27 10:55
閱讀 610·2019-08-27 10:55