控制反轉(zhuǎn)是面向?qū)ο缶幊讨械囊环N設(shè)計原則,可以用來減低計算機代碼之間的耦合度,還可以通過控制反轉(zhuǎn),讓對象在被創(chuàng)建的時候,由一個調(diào)控系統(tǒng)內(nèi)所有對象的外界實體將其所依賴的對象的引用傳遞給它。
控制反轉(zhuǎn)(Inversion of Control,縮寫為IoC),是面向?qū)ο缶幊讨械囊环N設(shè)計原則,可以用來減低計算機代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI),還有一種方式叫“依賴查找”(Dependency Lookup)。通過控制反轉(zhuǎn),對象在被創(chuàng)建的時候,由一個調(diào)控系統(tǒng)內(nèi)所有對象的外界實體將其所依賴的對象的引用傳遞給它。也可以說,依賴被注入到對象中。
控制反轉(zhuǎn)實現(xiàn)策略
IoC是一個很大的概念,可以用不同的方式實現(xiàn)。其主要形式有兩種:
依賴查找:容器提供回調(diào)接口和上下文條件給組件。EJB和Apache Avalon 都使用這種方式。這樣一來,組件就必須使用容器提供的API來查找資源和協(xié)作對象,僅有的控制反轉(zhuǎn)只體現(xiàn)在那些回調(diào)方法上(也就是上面所說的 類型1):容器將調(diào)用這些回調(diào)方法,從而讓應(yīng)用代碼獲得相關(guān)資源。
依賴注入:組件不做定位查詢,只提供普通的Java方法讓容器去決定依賴關(guān)系。容器全權(quán)負(fù)責(zé)的組件的裝配,它會把符合依賴關(guān)系的對象通過JavaBean屬性或者構(gòu)造函數(shù)傳遞給需要的對象。通過JavaBean屬性注射依賴關(guān)系的做法稱為設(shè)值方法注入(Setter Injection);將依賴關(guān)系作為構(gòu)造函數(shù)參數(shù)傳入的做法稱為構(gòu)造器注入(Constructor Injection)
控制反轉(zhuǎn)實現(xiàn)方法
實現(xiàn)數(shù)據(jù)訪問層
數(shù)據(jù)訪問層有兩個目標(biāo)。第一是將數(shù)據(jù)庫引擎從應(yīng)用中抽象出來,這樣就可以隨時改變數(shù)據(jù)庫—比方說,從微軟SQL變成Oracle。不過在實踐上很少會這么做,也沒有足夠的理由和能力去通過使用實現(xiàn)數(shù)據(jù)訪問層而對現(xiàn)有的應(yīng)用進行重構(gòu)。
第二個目標(biāo)是將數(shù)據(jù)模型從數(shù)據(jù)庫實現(xiàn)中抽象出來。這使得數(shù)據(jù)庫或代碼開源根據(jù)需要改變,同時只會影響主應(yīng)用的一小部分——數(shù)據(jù)訪問層。這一目標(biāo)是值得的,為了在現(xiàn)有系統(tǒng)中實現(xiàn)它進行必要的重構(gòu)。
模塊與接口重構(gòu)
依賴注入背后的一個核心思想是單一功能原則(single responsibility principle)。該原則指出,每一個對象應(yīng)該有一個特定的目的,而應(yīng)用需要利用這一目的的不同部分應(yīng)當(dāng)使用合適的對象。這意味著這些對象在系統(tǒng)的任何地方都可以重用。但在現(xiàn)有系統(tǒng)里面很多時候都不是這樣的。
隨時增加單元測試
把功能封裝到整個對象里面會導(dǎo)致自動測試?yán)щy或者不可能。將模塊和接口與特定對象隔離,以這種方式重構(gòu)可以執(zhí)行更先進的單元測試。按照后面再增加測試的想法繼續(xù)重構(gòu)模塊是誘惑力的,但這是錯誤的。
使用服務(wù)定位器而不是構(gòu)造注入
實現(xiàn)控制反轉(zhuǎn)不止一種方法。最常見的辦法是使用構(gòu)造注入,這需要在對象首次被創(chuàng)建時提供所有的軟件依賴。然而,構(gòu)造注入要假設(shè)整個系統(tǒng)都使用這一模式,這意味著整個系統(tǒng)必須同時進行重構(gòu)。這很困難、有風(fēng)險,且耗時。
推薦教程:《PHP》