控制反轉(ioc)的設計原則
--減輕元件間的依賴性及藕合性的設計原則
1.緣由
2、回顧物件導向思想
3.什麼是ioc
4、現行的幾種實現方式
5.結論
6.附錄
一、緣由
「萬事萬物皆有姻緣」,這一句話本是佛家偕語。不過筆者認為,這一句話也真是道出了世間萬事萬物的相輔相成的最徹底的一句解釋。在it這一行,更新換代比光速還快,我想同仁們都不會反駁我這句話吧!要不試試,從藝術性的工作,到工程化的專案,從面向過程到物件導向,從物件導向到面向方面!每一種思想都是那麼的偉大,每一種思想都沒有任何乙個人(還真是任何乙個人,不信的話,你找幾個大師級的人物問問,他們對哪一種思想完全理解並應用了?)完全理解並應用他,但新的思想又出來了(這種思想說的是軟體類的思想,程式設計的思想,當然沒有孔子孟子之類說)!好像說了這麼多,跟「萬事萬物皆有姻緣」沒有任何關係一樣,有,當然有,雖然這麼多的思想沒有任何乙個人完全貫通使用,但提出一種新的思想來使用,這是事物發展的需要,也是必然的趨勢,藝術性的程式設計不能實用於大型應用,因此提出工程化,面向過程使軟體公升級特別困難,因此懶惰的人們提出了物件導向的復用思想
,但物件導向的思想還是複雜,懶惰的人們就想要做更少的工作,因此提出了面向方面!「萬事萬物皆有姻緣」因為人們的懶惰,所以該放下的就放下了,重新拿起新的事物!那麼為什麼現在在程式設計界又提出了控制反轉(ioc)呢?下面我們看乙個經常引用的例子:
public class myclass
}現在想,如果我例項化_logger的方式變了,變成了:
logger _logger=logger.getlogger("my class debug");
你們想想是不是應該要改上面這個已經實現了的class呢?結果是肯定的,如果我有10個類,100個,那是不是要改10次,100次,我們稱這樣的軟體開發為藕合性太強或依賴太深!
「萬事萬物皆有姻緣」,控制反轉(ioc)就是為了解決這樣的問題而提出的原則!
二、物件導向思想回顧
首先我們回顧物件導向思想的一些內容,筆者在《軟體工程之物件導向軟體工程基礎(軟體工程實踐之三)》一文中概術物件導向時,物件導向=類+物件+繼承+通訊,物件導向就是這樣的一種思想。將元件分類,使用時再例項化,類與類之間可以繼承,他們通過通訊聯絡。在這裡我們要重新到乙個概念是服務,在很多物件導向文章中都提到了服務,那麼什麼是服務呢?即乙個類向另乙個類提供他想要的介面(或方法)。
如下例:
public classa
}public classb
}另兩個概念就是服務提供者與服務使用者,從上例可以看出,classa就是服務提供者-提供業務服務的一方 ,classb就服務使用者(也稱消費者)-使用業務服務的一方,在他們之間採用的聯絡的方式我們叫做通訊。 從上面的例子可以看出,服務提供者提供服務給消費者是特別直接的。這樣有如下壞處:
如果服務提供者變了呢?這樣是不是需要改動每個服務消費者? 這樣的一種依賴關係?我們用什麼來解決呢?ioc,控制反轉,它讓服務消費者不直接依賴於服務提供者!
三、什麼是控制反轉(ioc)?
一種讓服務消費者不直接依賴於服務提供者一 種元件設計方式,一種減少類與類之間依賴的設計原則,一種使服務與服務提供者完全分開的設計原則。我們將第乙個例子改進一下:
public class myclass
public void helloworld()
}現在呼叫時:
public class uselogger
}這樣,我們發現,整個使用logger的控制權全部在客戶端,即logger給myclass提供的服務的方式已經提交給了最終客房,完全取決於客戶端的需要,而不是在myclass呼叫服務時就依賴於logger了,這樣,服務提供者(logger)與消費者(myclass)之間的依賴就少了很多。這就是ioc的一種具體實現方式。
我們可以看出來,ioc更通俗的一種解釋就是:我在需要服務時,才告訴你怎麼去給我提供服務_logger的定義在myclass中只是乙個預留的定義,直到uselogger最終消費時才將具體怎麼使用logger通知給myclass.
四、控制反轉的幾種設計方式?
目前控制反轉的幾種實現方式:
.基於方法的(method-based ioc,type-0)
.基於介面的(inte***ce-based ioc,type-1)
.基於設值的(setter-based ioc,type-2)
.基於構造的(construtor-based ioc,type-3)
.type-0
基於方法的實現,主要依賴的是介面,,服務提供者將自己的接品傳遞給消費者方法,而不是將具體的實現型別傳遞過去,如下:
public inte***ce myclass
呼叫時:
logger _logger=logger.getlogger(this.getclass());
myclass myclass=new myclassimpl();
myclass.helloworld(_logger);
從上面可以看出,這樣logger與myclass的具體服務都依賴於介面myclass,logger提供服務時也止於方法上,logger服務提供與
myclassimpl消費之間隔開了,
.type-1
基於介面的實現,主要是採用容器來管理服務提供者,消費者只要實現服務提供者的介面就可以達到服務的目的了。
如下:public class myclassimpl implements myclass,logger
public void helloworld()
}怎麼呼叫 :
myclass myclass=new myclass();
logger _logger=logger.getlogger(this.getclass());
container.enablelogger(myclass,_logger);
myclass.helloworld();
可以看出,這樣的實現,必須要有珍上容器來檢查是否實現了logger接品,如果實現兇才能有效,否則就沒有作用。這樣的方法大大的減少了類與類之間的依賴.但必須要實現乙個容器。而且發現,每乙個實現的類都直接跟服務提供者(本例就是logger)的介面有了很直接的聯絡。
.type-2
的方式,就是通過bean的setter方法來給成員變數賦值,我們採用這種方式,就可以通過乙個配置檔案,配置好相應的bean,然後通過乙個容器來得到這個服務bean,這樣元件之間的依賴就已經少了。
如:public class myclass
public void helloworld()
}如spring採用的方式就是如此,它的全過程如下:
配置檔案:
呼叫:inputstream is=client.class.getclassloader().getresourceasstream("bean.xml");
beanfactory beans=new xmlbeanfacotory(is);
myclass myclass=(myclass)beans.getbean("myclass");
myclass.helloworld();
從上面可以看出,所有的服務提供類及消費類都已經通過乙個容器類來提取配置檔案統一管理了。
.type-3
基於構造的ioc,顧名思義,就是通過構造子來傳遞服務提供者的具體例項來例項化服務介面。
如下:public class myclass
public void helloworld()
} 這樣,註冊服務元件時在構造方法處完成,但,這樣一來繼承和構造時都有一定的困難。
五、結語
ioc的乙個真正的目的就是移植,減少元件的依賴性!但我們通過上面的例子,有沒有發現,這中間的依賴還很大呢?比如:如果我要將logger類移植使用另外乙個公司的產品的時候,這個時候,要移植的量是不是還很大呢?
六、附錄
1、術語
控制反轉(ioc-inversion of control);
容器(container),用於元件建立,生存的環境;
框架(framework::一組用於對特定領域構造的可復用的基礎元件
控制反轉(Ioc 的設計原則
控制反轉 ioc 的設計原則 減輕元件間的依賴性及藕合性的設計原則 1.緣由 2 回顧物件導向思想 3.什麼是ioc 4 現行的幾種實現方式 5.結論 6.附錄 一 緣由 萬事萬物皆有姻緣 這一句話本是佛家偕語。不過筆者認為,這一句話也真是道出了世間萬事萬物的相輔相成的最徹底的一句解釋。在it這一行...
好萊塢原則和IOC控制反轉
不要給 我們打 我們會給你打 don t call us,we ll call you 這是著名的 好萊塢原則。在好萊塢,把簡歷遞交給演藝公司後就只有回家等待。由演藝公司對整個娛樂項的完全控制,演員只能被動式的接受公司的差使,在需要的環節中,完成自己的演出。模板方法模式充分的體現了 好萊塢 原則。i...
IoC控制反轉
首先假設有乙個需求,類business需要呼叫類dependency的方法f 1 按照日常的做法,得到下面的 類dependency public class dependency 類business public class business public void dosomething 2 對...