1. 程式人生 > >IOC控制反轉是如何做到解耦和的

IOC控制反轉是如何做到解耦和的

     原來就瞭解過IOC控制反轉的設計思想,也看過一些文章,總覺得自己好像都看得懂,也知道在講什麼,知道其能很好的解耦和,卻隱隱約約又感覺自己好像還差了點什麼。這次有點小運氣,在寫自己的迷你框架的時候,寫到中途突然有種或豁然開朗的感覺,這裡就次記錄一下。

      先說一下最開始的想法,假設有一天你需要輸出各式各樣的東西(種類繁多),比如各式各樣的操作資訊、教程、漂亮的html靜態頁面、以及各式各樣的日誌等等等等,如果都堆到一個類裡面,顯然不利於輸出資訊的分類,影響程式碼可讀性,更不利於維護。這裡我打算是寫一個輸出的類,比如我想在Filter中輸出一個許可權不足的html頁面字串(有樣式),我希望以這樣的方式呼叫:String html_noAuthority = MyFormat.forType().html().problem().noAuthority().in("xxxProblem has encountered").out() ,如果是輸出做某件事成功,則以這樣的方式呼叫:MyFormat.forType().html().success().out() 或者   MyFormat.forType().html().success().in("register succeed").out()

最開始是這樣寫的:  以MyFormat.forType().html().problem().noAuthority()的呼叫為例

這樣寫確實是可以實現,但是其壞處也顯而易見,那就是寫的太死,耦合度太高了,從上面鏈式的呼叫中也可以看到,我每一個return的類都是指定的自己的實現類,設想假如別人(小紅)想用你的東西,他覺得你其他的輸出類都挺好,就是這個NoAuthority實現類的樣式寫的太醜了,別人想用他自己的NoAuthority_Beautiful實現類來代替你的類,但是以jar包形式的原始碼一般又是不可以修改的,即使可以修改,在業務變動的情況下需要頻繁地修改別人的原始碼。顯然,如果這麼寫肯定不合理。

那怎麼辦呢?有人想,直接在這些基礎上來一個函式過載,如果想用自己的實現類就傳一個自己的class進來,比如:

如果是這樣,好,那完蛋了。因為很顯然,返回值是介面,這麼寫就相當於沒寫,如果硬是要這麼寫,那隻能在該類的介面中多加一個重在函式,但是這樣,好,那也完蛋了(大量的實現類要修改,和程式碼重複)。如果只保留上圖中第二個函式,雖然可以可以滿足小紅的需求,但是每次都要傳一個Class進來,使得使用起來極其不爽(顯得多此一舉),同時try catch還會影響一點點速度,更重要的是,在每一個實現了這種帶Class引數的介面的類中,每一個函式都要try catch ,顯然冗餘了大量重複且不可觀的程式碼,於是乎三個字:完蛋了

所以看到這裡,在沒有IOC的情況下,整個小體系給人感覺就是一潭死水,沒有生機也不靈動

 

那使用了IOC思想後會怎樣呢?

     寫到這想必已經開始明瞭了,我們只需要將noAuthority該實現類的物件提出來 (即這裡定義的 ThiTierType  noAuthority引用),並對其提供一個set方法,然後,,,然後通過IOC容器配置相關bean,就可以對該引用瘋狂地賦值了!原來是寫死的NoAuthority實現類,現在管你想替換成什麼NoAuthority_Beautiful還是什麼NoAuthority_BeautifulPlus或是什麼NoAuthority_BeautifulSuperPlus都可以!

      那麼究竟是哪個環節一下子就輕鬆地打破了這灘死水呢?關鍵其實就是看究竟是誰創建出了NoAuthority類的物件

在傳統的方式中,是noAuthority函式主動地去建立了NoAuthority類物件給別人用,而在IOC思想中,是IOC容器建立了NoAuthority類物件然後給noAuthority函式用(關係被反轉了)。 那為什麼這種反轉能帶來如此強大的靈活性和多樣性呢?

          我們可以這樣想,傳統方式中是程式碼指定建立什麼類,可程式碼是死的,程式碼指定建立什麼就只能建立什麼。在IOC中是人指定建立什麼類(即配置),程式碼是死,但人是活的,你想換成什麼就配置什麼就可以了。

 

         其實仔細想一下最基本的面向物件思想也能想明白,為了解耦和,一個類或者一個函式,更應該專注於一件事情,就像一個伐木工人伐木,伐木工人更希望你給他一個斧子,而不是他自己去建造一把斧子,然後再去伐木,前者的耦合度是一(伐木),後者的耦合度是二(造斧頭+伐木)  。如果對應到程式碼就是一個伐木工人類,內部有一個斧子引用,有一個伐木方法,這個伐木工人(類)更希望他在伐木前(函式呼叫)就把斧子已經做好了(函式呼叫前被建立而不是函式過程中再建立)

         而回到我上面的程式碼中,也正是因為IOC的思想,別人不僅能用我寫的類,不想用了還能替換成他自己的類,這其實也就無形中降低了耦合度,增加了多樣性