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