ioc:英文全稱:inversion of control,中文名稱:控制反轉,它還有個名字叫依賴注入(dependency injection)。
作用:將各層的物件以松耦合的方式組織在一起,解耦,各層物件的呼叫完全面向介面。當系統重構的時候,**的改寫量將大大減少。
理解依賴注入:
當乙個類的例項需要另乙個類的例項協助時,在傳統的程式設計過程中,通常有呼叫者來建立被呼叫者的例項。然而採用依賴注入的方式,建立被呼叫者的工作不再由呼叫者來完成,因此叫控制反轉,建立被呼叫者的例項的工作由ioc容器來完成,然後注入呼叫者,因此也稱為依賴注入。
舉個有意思的例子(**於網際網路)
假如我們要設計乙個girl和乙個boy類,其中girl有kiss方法,即girl想要kiss乙個boy,首先問題是girl如何認識boy?
在我們中國常見的mm認識gg的方式有以下幾種:
a 青梅竹馬 b 親友介紹 c 父母包辦
哪一種是最好的?
1.青梅竹馬:很久很久以前,有個有錢的地主家的一閨女叫lily,她老爸把她許配給縣太爺的兒子jimmy,屬於指腹為婚,lily非常喜歡kiss,但是只能kiss jimmy
public class lily
public void kiss()
} public class jimmy
}
這樣導致lily對jimmy的依賴性非常強,緊耦合。
2.親友介紹:經常kiss同乙個人令lily有些厭惡了,她想嘗試新人,於是與jimmy分手了,通過親朋好友(中間人)來介紹
public class lily
public void kiss()
}
親友介紹,固然是好。如果不滿意,儘管另外換乙個好了。但是,親友boyfactory經常是以singleton的形式出現,不然就是,存在於globals,無處不在,無處不能。實在是太繁瑣了一點,不夠靈活。我為什麼一定要這個親友摻和進來呢?為什麼一定要付給她介紹費呢?萬一最好的朋友愛上了我的男朋友呢?
3.父母包辦:一切交給父母,自己不用非吹灰之力,lily在家只kiss
public class lily
public void kiss()
}
well,這是對girl最好的方法,只要想辦法賄賂了girl的父母,並把boy交給他。那麼我們就可以輕鬆的和girl來kiss了。看來幾千年傳統的父母之命還真是有用哦。至少boy和girl不用自己瞎忙乎了。這就是ioc,將物件的建立和獲取提取到外部。由外部容器提供需要的元件。
在設計模式中我們應該還知道依賴倒轉原則,應是面向介面程式設計而不是面向功能實現,好處是:多實現可以任意切換,我們的boy應該是實現kissable介面。這樣一旦girl不想kiss可惡的boy的話,還可以kiss可愛的kitten和慈祥的grandmother
好在.net中微軟有乙個輕量級的ioc框架unity,支援構造器注入,屬性注入,方法注入如下圖所示
具體使用方法如下圖所示
using system;
using microsoft.practices.unity;
} public inte***ce ikiss
public class lily:ikiss
public void kiss()
} public class boy : ikiss
} }
如果採用配置檔案註冊的話
<?xml version="1.0" encoding="utf-8" ?>
配置的後台**:
unityconfigurationsection configuration = configurationmanager.getsection(unityconfigurationsection.sectionname)
as unityconfigurationsection;
configuration.configure(container, "defaultcontainer");
可以通過方法resolveall來得到所有註冊物件的例項:
var instances = container.resolve();
martin fowler在那篇著名的文章《inversion of control containers and the dependency injection pattern》中將具體依賴注入劃分為三種形式,即構造器注入、屬性(設定)注入和介面注入,習慣將其劃分為一種(型別)匹配和三種注入:
我們建立乙個控制台程式,定義如下幾個介面(ia、ib、ic和id)和它們各自的實現類(a、b、c、d)。在型別a中定義了3個屬性b、c和d,其型別分別為介面ib、ic和id。其中屬性b在構在函式中被初始化,以為著它會以構造器注入的方式被初始化;屬性c上應用了dependencyattribute特性,意味著這是乙個需要以屬性注入方式被初始化的依賴屬性;屬性d則通過方法initialize初始化,該方法上應用了特性injectionmethodattribute,意味著這是乙個注入方法在a物件被ioc容器建立的時候會被自動呼叫。
public inte***ce ia
public inte***ce ib
public inte***ce ic
public inte***ce id
public class a : ia
[dependency]
public ic c
public id d
public a(ib b)
[injectionmethod]
public void initalize(id d)
} public class b : ib
public class c : ic
public class d : id
然後我們為該應用新增乙個配置檔案,並定義如下一段關於unity的配置。這段配置定義了乙個名稱為defaultcontainer的unity容器,並在其中完成了上面定義的介面和對應實現類之間對映的型別匹配。
<?xml version="1.0" encoding="utf-8" ?>
最後在main方法中建立乙個代表ioc容器的unitycontainer物件,並載入配置資訊對其進行初始化。然後呼叫它的泛型的resolve方法建立乙個實現了泛型介面ia的物件。最後將返回物件轉變成型別a,並檢驗其b、c和d屬性是否是空
class program
",a.b==null?"yes":"no");
console.writeline("a.c==null?", a.c == null ? "yes" : "no");
console.writeline("a.d==null?", a.d == null ? "yes" : "no");
} }
}
從如下給出的執行結果我們可以得到這樣的結論:通過resolve方法返回的是乙個型別為a的物件,該物件的三個屬性被進行了有效的初始化。這個簡單的程式分別體現了介面注入(通過相應的介面根據配置解析出相應的實現型別)、構造器注入(屬性b)、屬性注入(屬性c)和方法注入(屬性d)
a.b == null ? no
a.c == null ? no
a.d == null ? no
理解依賴注入(IOC)
ioc 英文全稱 inversion of control,中文名稱 控制反轉,它還有個名字叫依賴注入 dependency injection 作用 將各層的物件以松耦合的方式組織在一起,解耦,各層物件的呼叫完全面向介面。當系統重構的時候,的改寫量將大大減少。理解依賴注入 當乙個類的例項需要另乙個...
ioc(依賴 依賴倒置 依賴注入)
先看一下這個大佬的部落格 我只是畫個圖 1.依賴 這個很不友好,要換別的player或者meidafile要動operation 2.依賴倒置 這個好很多了,加了兩個介面,要換別的player或者meidafile,不用動operation 3.ioc 控制反轉 控制權是我們使用者自己,如果是spr...
Spring 學習筆記 IOC 依賴注入
簡述 spring 學習 ioc 依賴注入 1 直接使用原始類建立bean 2 使用工廠方法建立bean 3 使用工廠類建立bean 1 setter injection 2 constructor injection 建構函式注入 1 inner beans 2 collections map 3...