iOS 元件化方案
現在很多公司在業務擴張到一定程度或者商業模式跑通之後就會考慮到元件化方案,而元件化方案目前主流的做法就是以下三種,這裡我們將就元件化方案談談自己的思考。
- URL Scheme
- Protocol Class
- Target Action
URL Scheme
方案
實現方式:
在啟動時,註冊元件提供的服務(註冊URL以及關聯服務Block),然後在使用時,通過URL直接呼叫(openURL); - 使用URL處理本地跳轉邏輯 - 註冊元件,記憶體中維護URL註冊服務
優點:
- 統一了不同平臺的客戶端在跳轉上的不一致
- 處理網頁跳轉上較為方便
缺點:
- url引數受限(例如非字串型別,UIImage,XXModel,NSData等)
- 業務分散,耦合多
- 元件很多的情況下,可能會影響到記憶體
Protocol Class
方案
實現方式:
通過Protocol定義服務介面,元件通過實現該介面來提供服務,最終的實現就是將Protocol和Class對映在一起,同時在記憶體中儲存一張對映表,使用的時候,通過Protocol去獲取Class對應的服務。 - 增加 Protocol Wrapper(包裝) 層 - 中介軟體返回 Protocol 對應的 Class - 解決硬編碼的問題
優點:
- 協議介面規範,遵循依賴反轉原則
缺點:
- 缺少統一排程層,元件方法呼叫分散,難於集中管理(團隊規模大,架構管控越重要)
- 架構的靈活性不夠高
Target Action
方案
實現方式:
Target Action這個方案是基於ObjC
的runtime
、category
特性動態獲取模組,例如通過NSClassFromString
獲取類並建立例項,通過 performSelector
+ NSInvocation
動態呼叫方法。
首先每個模組需要配置Target和Category,其中Target是每個元件對應一個或者多個Target,Category是中間層Mediator的分類,使用分類的目的是為了讓Mediator的業務程式碼分離,從而降低Mediator中的依賴和耦合性。 那麼中間層Mediator是如何找到並呼叫元件的呢?這裡正是利用了runtime的反射機制,在Category中找到對應Target以及呼叫Target對應的Action。
CTMediator正是採用的Target Action
方案,巧妙的使用了cocoaTouch提供的反射機制,方法簽名與命令模式,簡單又完美的解決了元件間的解耦問題。
- 抽離業務層邏輯
- 提供由中間層呼叫邏輯
- 中間層實現上使用Runtime反射
優點:
- 解耦,只存在元件依賴中間層(單向依賴)
- 利用 Category 可以明確宣告的介面,進行編譯檢查
- 統一處理了所有元件間呼叫入口,方便管理
缺點:
- 每個元件的Category對應一個Target,Category中的Action對應Target中的Action。(此類的程式碼量很多)
- 有硬編碼的問題,各種定義的string
元件化的思考
前面寫到元件化方案的各個差異,那麼來談談我自己對元件化架構的看法。
首先元件化的最大目的就是解耦合,易擴充套件。首先我們需要考慮的應該是如何將模組直接解耦,如何將模組細分。模組劃分的原則要基於什麼,這個要結合業務去拆分。
然後我們再次基礎上搭建出容易維護和擴充套件的架構,即遵循SOLID
以下五個原則:
- 單一功能原則
- 開閉原則
- 里氏替換原則
- 介面隔離原則
- 依賴反轉原則
最後將拆分好的模組通過cocoapod
打包成庫進行管理。
等等,這就結束了嗎?當然還沒完呢,在這裡元件和元件之間的呼叫還是沒有解耦,所以需要我們的元件化架構出場了,我們需要理清各個元件之間的依賴關係以及呼叫邏輯,劃分層次。元件間的分層可以分為: - 底層(基礎元件) - 中間層(通用的業務元件) - 業務層
目前元件化的架構上主要分為協議式Protocol-Class
(蘑菇街方案)以及中間者Target-Action
(CTMediator) 兩種,在我看來前者可能適合側重點在HTML上業務更多的團隊。協議式最大的詬病就是缺乏統一的管理。而後者的優點體現在架構上容易管控,易擴充套件,所以更為推薦使用後者。
當然最終如何選擇架構,目的都是使業務解耦,使得專案更容易維護以及擴充套件新業務。很多人會追求完美主義,追求理想中的解耦。在我看來元件化的重點是業務層的解耦,元件化的基礎是有一個好的基建。
- LeetCode 初級演算法之陣列(上),看看你都學會了嗎?
- LeetCode 初級演算法之連結串列,看看你都學會了嗎?
- LeetCode 初級演算法之字串(上),看看你都學會了嗎?
- 純程式碼佈局,也可以一樣的簡潔
- UIStackView之一問一答
- 使用UIStackView來簡化iOS的介面佈局
- 夏天來了,iOS開發者們該如何減少App耗電?(上)
- 夏天來了,App開發者們如何看待手機發燙問題?
- 聊聊iOS中UITableView複用的那些事
- 曾經經典的微信打飛機遊戲還有人記得嗎?
- iOS 原生渲染與 Flutter 有什麼區別 (上)
- 瞭解 Mach-O檔案
- CocoaPods中podsepc檔案設定詳解
- iOS 原生渲染與 Flutter 有什麼區別 (下)
- 簡單瞭解 iOS CVPixelBuffer (上)
- 談談 iOS 包瘦身方案
- 播放器重構的探索之路
- 如何使用CocoaPods製作私有庫
- iOS 元件化方案