Ioc與DI

關於 IOC 和 DI 的理解
IOC:Inversion of Control 控制反轉
DI:Dependency Injection 依賴注入
控制反轉,從字面意思來看,就是控制權又被動變主動,最後又變回被動。
舉個例子:
你的主管要求你作一件事情,這個時候就存在這麼幾個過程,
主管命令你作事情(這個時候主動權在主管,你是被動的)
你接到命令作事情(這個時候主題是你,你是主動的,控制權在你手裏)
你完成事情(這個時候主題依然是你,控制權在你手裏)
報告主管作完事情(主動權又叫交到主管手裏了)
上面的整個過程就完成了一次 IOC,從上面能夠看出,IOC 的基本思想是控制權
的轉換過程。
舉個代碼的例子:
假若有 Class A, Class B,在 A 內部會初始化一個 B,調用 B 的一個方法 DoMethod
public  Class  B
{
public  void  DoMethod()
{
//  do  somthing;
}
}
public  Class  A
{
public  void  Excute()
{
B  b  =  new  B();
b.DoMethod();
}
}
假如在 Main 函數中以下執行:
A  a  =  new  A();
a.Excute(); 
從這兩行代碼來看,事實上也存在一個 IOC 的過程,a——>b——>a,理解的關
鍵點就在在 A 的內部調用 Excute 的時候,方法 b.DoMethod 的執行。
理解了 IOC,咱們再看一下 DI。
從上面 A 調用 B 咱們能夠看出,在初始化一個 A 的實例時,也必須實例化一個 B,
也就是說若是沒有 B 或者 B 出了問題,A 就沒法實例化,這就產生了一種依賴,
就是 A 依賴 B,這種依賴從設計的角度來講就是耦合,顯然它是沒法知足高內聚
低耦合的要求的。這個時候就須要解耦,固然解耦有不少種方法,而 DI 就是其
中一種。無論任何一種解耦方法,都不是說使 A 和 B 徹底沒有關係,而是把這
種關係的實現變得隱晦,不那麼直接,可是又很容易實現,並且易於擴展,不
像上面的代碼那樣,直接 new 一個 B 出來。
那爲何咱們老是把 IOC 和 DI 聯繫到一塊兒呢?是由於 DI 的基本思想就是 IOC,
而體現 IOC 思想的方法還有另一個,那就是 Service Locator,這個方法好
像涉及到的不多。
DI,依賴注入,從字面意思就能夠看出,依賴是經過外接注入的方式來實現的。
這就實現瞭解耦,而 DI 的方式一般有三種,
構造器注入
屬性設置器注入
接口注入(我感受接口注入是同時存在於上兩種注入方式的,而不該該獨立
出來)
以上的闡述只是爲了先讓咱們能對 IOC 和 DI 有一個感性的理解,那麼 IOC 真正
解決的問題是什麼呢?
咱們講了那麼多主動被動的問題,那咱們是從什麼視角來看待這個問題的呢?
所謂爲何你是主動,而我不是主動呢?這就須要一個參照物,那這個參照物
是什麼呢?就是容器,在容器中來體現主動和被動。
用白話來說,就是由容器控制程序之間的關係,而非傳統實現中,由程序代碼
直接操控。這也就是所謂「控制反轉」的概念所在:控制權由應用代碼中轉到
了外部容器,控制權的轉移,是所謂「反轉」,這是一般對 IOC 的一個解釋。
從容器的角度來看主動和被動,和由容器來控制程序之間的關係,應該是相通
的,是一個意思。
IOC 要解決的就是程序之間調用的一個問題,它應該是一個思想層面的東西,是
一箇中心,就像一支樂隊的指揮,而程序就是樂器,經過指揮來協調各類樂器,
來演奏出美好的音樂來。
-------------我是華麗麗的分割線,如下爲引用--------------------
IOC 的深入理解 
IoC 是什麼?Inversion of Control,即反轉控制,或許說爲依賴注入更爲合適。
IoC 就是 IoC,不是什麼技術,與 GoF 同樣,是一種設計模式。
Interface Driven Design 接口驅動,接口驅動有不少好處,能夠提供不一樣
靈活的子類實現,增長代碼穩定和健壯性等等,可是接口必定是須要實現的,
也就是以下語句早晚要執行:AInterface a = new AInterfaceImp(); 這樣一
來,耦合關係就產生了,如:
Class A{
AInterface a;
A(){}
aMethod(){
a = new AInterfaceImp();
}
}
ClassA 與 AInterfaceImp 就是依賴關係,若是想使用 AInterface 的另一個實
現就須要更改代碼了。固然咱們能夠創建一個 Factory 來根據條件生成想要的
AInterface 的具體實現,即:
InterfaceImplFactory{
AInterface create(Object condition){
if(condition = condA){
return new AInterfaceImpA();
}elseif(condition = condB){
return new AInterfaceImpB();
}else{
return new AInterfaceImp();
}
}
}
表面上是在必定程度上緩解了以上問題,但實質上這種代碼耦合並無改變。
經過 IoC 模式能夠完全解決這種耦合,它把耦合從代碼中移出去,放到統一的
XML 文件中,經過一個容器在須要的時候把這個依賴關係造成,即把須要的接口
實現注入到須要它的類中,這可能就是「依賴注入」說法的來源了。
IOC 模式,系統中經過引入實現了 IOC 模式的 IOC 容器,便可由 IOC 容器來
管理對象的生命週期、依賴關係等,從而使得應用程序的配置和依賴性規範與
實際的應用程序代碼分開。其中一個特色就是經過文本的配件文件進行應用程
序組件間相互關係的配置,而不用從新修改並編譯具體的代碼。
當前比較知名的 IOC 容器有:Pico Container、Avalon 、Spring、JBoss、
HiveMind、EJB 等。
在上面的幾個 IOC 容器中,輕量級的有 Pico Container、 Avalon、 Spring、
HiveMind 等,超重量級的有 EJB,而半輕半重的有容器有 JBoss,Jdon 等。
能夠把 IoC 模式看作是工廠模式的昇華,能夠把 IoC 看做是一個大工廠,
只不過這個大工廠裏要生成的對象都是在 XML 文件中給出定義的,而後利用 Java 
的「反射」編程,根據 XML 中給出的類名生成相應的對象。從實現來看,IoC 是
把之前在工廠方法裏寫死的對象生成代碼,改變爲由 XML 文件來定義,也就是
把工廠和對象生成這二者獨立分隔開來,目的就是提升靈活性和可維護性。
IoC 中最基本的 Java 技術就是「反射」編程。反射又是一個生澀的名詞,
通俗的說反射就是根據給出的類名(字符串)來生成對象。這種編程方式能夠
讓對象在生成時才決定要生成哪種對象。反射的應用是很普遍的,象
Hibernate、String 中都是用「反射」作爲最基本的技術手段。
在過去,反射編程方式相對於正常的對象生成方式要慢 10 幾倍,這也許也
是當時爲何反射技術沒有普通應用開來的緣由。但經 SUN 改良優化後,反射
方式生成對象和一般對象生成方式,速度已經相差不大了(但依然有一倍以上
的差距)。
IoC 最大的好處是什麼?由於把對象生成放在了 XML 裏定義,因此當咱們需
要換一個實現子類將會變成很簡單(通常這樣的對象都是現實於某種接口的),
只要修改 XML 就能夠了,這樣咱們甚至能夠實現對象的熱插撥(有點象 USB 接
口和 SCIS 硬盤了)。
IoC 最大的缺點是什麼?(1)生成一個對象的步驟變複雜了(其實上操做
上仍是挺簡單的),對於不習慣這種方式的人,會以爲有些彆扭和不直觀。(2)
對象生成由於是使用反射編程,在效率上有些損耗。但相對於 IoC 提升的維護
性和靈活性來講,這點損耗是微不足道的,除非某對象的生成對效率要求特別
高。(3)缺乏 IDE 重構操做的支持,若是在 Eclipse 要對類更名,那麼你還需
要去 XML 文件裏手工去改了,這彷佛是全部 XML 方式的缺憾所在。
IOC 實現初探
IOC 關注服務(或應用程序部件)是如何定義的以及他們應該如何定位他們依
賴的其它服務。一般,經過一個容器或定位框架來得到定義和定位的分離,容
器或定位框架負責:
保存可用服務的集合
提供一種方式將各類部件與它們依賴的服務綁定在一塊兒
爲應用程序代碼提供一種方式來請求已配置的對象(例如,一個全部依賴都知足
的對象), 這種方式能夠確保該對象須要的全部相關的服務均可用。
現有的框架實際上使用如下三種基本技術的框架執行服務和部件間的綁定: 
類型 1 (基於接口): 可服務的對象須要實現一個專門的接口,該接口提供了一
個對象,能夠從用這個對象查找依賴(其它服務)。早期的容器 Excalibur 使用
這種模式。
類型 2 (基於 setter): 經過 JavaBean 的屬性(setter 方法)爲可服務對象指定
服務。HiveMind 和 Spring 採用這種方式。
類型 3 (基於構造函數): 經過構造函數的參數爲可服務對象指定服務。
PicoContainer 只使用這種方式。HiveMind 和 Spring 也使用這種方式。
-----------------華麗麗的分割線,引用結束-------------------------Interface Driven Design 接口驅動
接口驅動有不少好處,能夠提供不一樣靈活的子類實現,增長代碼穩定和健壯性
等等,可是接口必定是須要實現的,也就是以下語句早晚要執行:AInterface a 
= new AInterfaceImp(); 這樣一來,耦合關係就產生了。
如:
Class A
{
AInterface a;
A(){}
aMethod()
{
a = new AInterfaceImp();
}
}
ClassA 與 AInterfaceImp 就是依賴關係,若是想使用 AInterface 的另一個實
現就須要更改代碼了。
固然咱們能夠創建一個 Factory 來根據條件生成想要的 AInterface 的具體實現,
即:
InterfaceImplFactory
{
AInterface create(Object condition)
{
if(condition = condA)
{
return new AInterfaceImpA();
}
elseif(condition = condB)
{
return new AInterfaceImpB();
}
else
{
return new AInterfaceImp();
}
}
}
表面上是在必定程度上緩解了以上問題,但實質上這種代碼耦合並無改變。
經過 IoC 模式能夠完全解決這種耦合,它把耦合從代碼中移出去,放到統一的
XML 文件中,經過一個容器在須要的時候把這個依賴關係造成,即把須要的接口
實現注入到須要它的類中,這可能就是「依賴注入」說法的來源了。
IOC 模式系統中,經過引入實現 IOC 模式的 IOC 容器,便可由 IOC 容器來管理對
象的生命週期、依賴關係等,從而使得應用程序的配置和依賴性規範與實際的
應用程序代碼分開。其中一個特色就是經過文本的配置文件進行應用程序組件
間相互關係的配置,而不用從新修改並編譯具體的代碼。
當前比較知名的 IOC 容器有: Pico Container、 Avalon 、 Spring、 JBoss、 HiveMind、
EJB 等。其中,輕量級的有 Pico Container、Avalon、Spring、HiveMind 等,
超重量級的有 EJB,而半輕半重的有容器有 JBoss,Jdon 等。
能夠把 IoC 模式看作是工廠模式的昇華,能夠把 IoC 看做是一個大工廠,只不
過這個大工廠裏要生成的對象都是在 XML 文件中給出定義的,而後利用 Java 的
「反射」編程,根據 XML 中給出的類名生成相應的對象。從實現來看,IoC 是把
之前在工廠方法裏寫死的對象生成代碼,改變爲由 XML 文件來定義,也就是把
工廠和對象生成這二者獨立分隔開來,目的就是提升靈活性和可維護性。
IoC 中最基本的 Java 技術就是「反射」編程。反射又是一個生澀的名詞,通俗
的說反射就是根據給出的類名(字符串)來生成對象。這種編程方式可讓對
象在生成時才決定要生成哪種對象。反射的應用是很普遍的,象 Hibernate、
String 中都是用「反射」作爲最基本的技術手段。
IoC 最大的好處是什麼?由於把對象生成放在了 XML 裏定義,因此當咱們須要換
一個實現子類將會變成很簡單(通常這樣的對象都是現實於某種接口的),只
要修改 XML 就能夠了。 
編程

相關文章
相關標籤/搜索