iOS學習之入門組件化

timg.jpg

寫在前面

  • 組件化是近年來比較火的一個概念,現(xiàn)在很多公司的 app 包含的內(nèi)容和模塊越來越多,代碼的維護和迭代也會產(chǎn)生很大的困難,每個模塊各司其職,并且可以做到很好的復用。當我們的工程越來越大,而我們想要測試某一個部分的功能時,就會產(chǎn)生很多不必要的額外工作,這時,我們想到了將整個 app 拆分成很多組件,每個組件可以單獨編譯運行進行測試,并且當我們參與項目的人員越來越多時,代碼量越來越大時,單工程代碼更加難以維護于是,也就有了組件化的概念,實際上組件化也就是模塊化一種的表現(xiàn)方式,要理解組件化的思想其實并不困難?,F(xiàn)在我就介紹一下我最近學習組件化時拜讀的文章以及一些自己的想法。

了解

  • 首先需要理解模塊化與解耦的概念,推薦這篇文章:模塊化與解耦 這篇文章的作者就以下幾個問題探討了一下模塊化:

    • 為什么需要模塊化?
    • 模塊化的設(shè)計原則
    • 模塊化的優(yōu)缺點
    • 解耦的概念和原則
    • 模塊之間解耦的方式

    在這篇文章中我很容易的理解了模塊化的基本概念,為什么我們需要模塊化,以及如何設(shè)計和實現(xiàn)模塊化。

  • bang 神的分析 iOS組件化方案探索 ,這篇文章淺顯易懂的向我們講述了當前幾個組件化方案的實行原理,也通俗易懂的對他們的不同之處和優(yōu)缺點進行了比較說明,讓我這種小白也能夠豁然開朗。

  • 淺析iOS組件化設(shè)計 作者由為什么要組件化?如何組件化?和組件化有什么優(yōu)缺點?三個方面來闡述了自己對于組件化的觀點。

  • 相信看完這三篇文章的你已經(jīng)對組件化有了一個基本的概念,接著我們可以看一看 bang 神博客中指的這三種組件化方案的原版究竟是怎樣的

入門

方案1:

  • 先來看一看蘑菇街的組件化實現(xiàn)方案:蘑菇街的組件化之路 就是在這篇文章中,limboy 提出了使用 URLRouter 的方式來進行組件化,實現(xiàn)組間通信。
    • 這種方法的優(yōu)點就是做法十分簡便,我們甚至在不需要組件化的場景也可以隨意實現(xiàn)兩個界面之間的跳轉(zhuǎn),并且邏輯也十分容易理解。
    • 我們只需要一個中間件 Mediator 類來提供注冊 URL 和 openURL 兩種接口即可。組件 A 持有 Mediator 類,他需要將自己注冊到注冊表中。而當組件 B 想調(diào)用組件 A 時,只需要調(diào)用 openURL 方法將組件 A 當時注冊的 url 傳遞過去即可。
    • 缺點也非常明顯:URL之間的跳轉(zhuǎn)本來應該是應用之間進行的調(diào)用,而我們在這里卻讓他服務于應用內(nèi)之間的調(diào)用,造成了讓遠程應用之間的跳轉(zhuǎn)服務于本地應用,而遠程調(diào)用無法傳遞特殊的非常規(guī)對象,并且我們有時候在找不到頁面時,針對遠程跳轉(zhuǎn)和應用內(nèi)跳轉(zhuǎn)需要作出不同的響應,這時URL調(diào)用就會出現(xiàn)問題。
    • 并且我們需要在內(nèi)存中維護一個 register 表,當我們不需要表中的某個元素時,忘記刪除可能會帶來一些比較嚴重的后果。
    • 這種方式的硬編碼也十分明顯

方案2:

  • 而隨后 casatwy 大神便寫了一篇文章來闡述自己所理解的組件化應有的樣子,反駁了蘑菇街中的使用 URLRouter 進行處理的做法,并且解釋了自己這樣做的原因:iOS應用架構(gòu)談 組件化方案

    • casatwy 的這種方案邏輯上是很容易理解的,即我們有一個 Mediator 類,這個類作為中間件來幫助組件實現(xiàn)他們之間的調(diào)用,使得他們不必直接互相引用對方。每一個組件只要持有一個中間件,那么就可以聯(lián)系任意它想要調(diào)用的組件。類似于這樣,

      image
      而這樣產(chǎn)生的問題也十分明顯,即 Mediator 也持有每個組件,如果組件一旦多了起來,Mediator 將會臃腫不堪。為了解決這個問題,他選擇了利用 OC 語言的特性 runtime 來實現(xiàn),具體的做法就是依賴反射,使得 Mediator 類中可以依靠 NSClassFromString(), NSSelectorFromString() 等方法正確的獲取類和對象,也就不需要依賴組件了。

    • 但是這樣出現(xiàn)的問題就是一旦組件多了起來, Mediator 就會越來越臃腫,因為每個組件都需要 Mediator 來處理他們對應的方法,并且實際上每個處理的方法邏輯上都大致相同,使用反射機制,這樣就產(chǎn)生了大量的重復代碼。

    • 所以在實際的代碼中,casatwy 使用了 target - action 方案:即由每一個組件來具體實現(xiàn)關(guān)于 Mediator的 分類,由他們自己給 Mediator 添加對應的方法,這樣就解決了代碼量臃腫的問題,并且每個組件只需要維護自己那部分的關(guān)于 Mediator 的分類,工作量也有了減少。

    • 并且 Mediator 中對外部調(diào)用和 app 內(nèi)部調(diào)用做了區(qū)分,在對外部參數(shù)進行處理之后,到最后都是調(diào)用同樣的 performSelector:withParam: 方法,實現(xiàn)了本地調(diào)用為外部調(diào)用服務的宗旨。

    • 對于通過 Mediator 對各個組件的調(diào)用,實際上也由每個組件自己的 Target 類來維護,這個 Target_A 類附屬于組件 A,并且實現(xiàn)了組件A所有能夠?qū)ν馓峁┑姆椒?,最后的代碼結(jié)構(gòu)也就是這樣的

組件化.png
  • 這種方案的邏輯十分清晰,即 target - action 通過對 Category ModuleAActions 進行調(diào)用來實現(xiàn)對 Mediator 中方法的調(diào)用,進行解析轉(zhuǎn)發(fā)最后實現(xiàn)特定組件中方法的調(diào)用。需要注意的是這里最后的特定組件即是圖上的 Target_A,并不是 DemoModulADteailViewController,因為 Target_A 相當于 DemoModulADteailViewController 的門,只需要實例化了 Target_A ,就可以對 DemoModulADteailViewController 對外的方法進行調(diào)用,這樣隱藏了 DemoModulADteailViewController 的內(nèi)部結(jié)構(gòu),保持它原本的邏輯不被破壞,符合黑盒模型。

  • 這種方案的優(yōu)點在于可以完全針對不同的情況,各種類型的參數(shù)進行調(diào)用,并且不需要在系統(tǒng)內(nèi)維護路由表,只需要在用到的時候進行 runtime 轉(zhuǎn)發(fā)即可。

  • 缺點在于中間件中其實也有部分硬編碼,但是都被封裝到中間件中了,外界并看不到。個人感覺理解起來相對較難,使用起來也比較麻煩。

方案3:

  • 之后 limboy 也迅速更新了一篇文章來作為回應:蘑菇街組件化之路續(xù) 在這篇文章中,為了解決 casatwy 所提出來的問題,使用了與 target - action 類似的方案:protocol - class 方案來實行組件化。
    • 所謂 protocol - class 方案即中間件 Mediator 首先需要有 registerClass:forProtocol: 方法來注冊實現(xiàn)了這個協(xié)議的類,在 Mediator 內(nèi)部維護一個 map,來注冊這個 class 和 protocol,這本質(zhì)上和 URLRouter 的注冊類似,因為 Mediator 為單例,所以也會造成內(nèi)存常駐 。Mediator 同時向外提供 classForProtocol: 方法,來返回特定的類,并沒有人關(guān)心這個 class 是什么,它只需要實現(xiàn)了這個 protocol 即可。
    • 然后定義一個公共的 Protocol.h 文件,這個文件中定義了所有的接口和他們所聲明的方法,而具體組件需要做的就是實現(xiàn)這個接口,并且把自己注冊到 Mediator 中。
    • 調(diào)用時,其他組件只需要聲明 Mediator 頭文件,然后調(diào)用 Class class = [Mediator classForProtocol:XXXProtocol] 即可獲取對象。這個被獲取的對象應該為一個組件的 Entry 類,類似方案2 的 Target,在這個 Entry 類中將自己注冊到 Mediator 中并且實現(xiàn)協(xié)議中的方法。
    • 總的來說這種方案是方案1的一個拓展,滿足了方案1中組件調(diào)用時不適用條件下的使用,總的來說和方案1的原理大致相同,理解起來也比較簡單,并且也不存在方案1和2中的硬編碼問題。
    • 缺點在于,當我們想要修改某一個組件對外方法時,我們還需要先修改 protocol,當我們想獲取 Class 時,我們還要先將 class 的實例化傳遞給調(diào)用方,然后再由調(diào)用方來實例化對象。非常不方便。

擴展

  • 對于組件化這一部分,我也閱讀了一些比較好的文章,在這里分享一下:
    • 組件化----路由設(shè)計思路分析 ,這篇文章比較長,系統(tǒng)的分析了一下路由設(shè)計的思想和每個組件化方案的基本原理。
    • 組件架構(gòu)漫談 在這篇文章中,作者首先詳細分析了上述三種方案的原理差異以及使用上的便利度,最后作者也基于自己的想法總結(jié)分享了他們公司組件化的方案。
    • iOS組件化思路-大神博客研讀和思考 作者首先分析了三種組件化方案的原理,接著描述了組件化過程中需要注意的問題,最后也有自己的總結(jié)和針對于自身項目組件化思路。

總結(jié)

  • 到現(xiàn)在總算是對組件化入了門,相信看完這幾篇文章的你們也跟我是同樣的感覺。實際上我對于組件化并沒有實際的經(jīng)驗,因為曾經(jīng)做過的項目都比較小,最多用到了路由來實現(xiàn)幾個控制器之間的跳轉(zhuǎn)。通過這次學習,我也對項目的結(jié)構(gòu)有了一個重新的認識,在以后的學習中也會在這方面不斷的探索。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容