Android-模塊化-面向接口編程

一崇败、概述

隨著業(yè)務的發(fā)展盅称,工程的逐漸增大與開發(fā)人員增多,很多工程都走向了模塊化后室、組件化缩膝、插件化道路,來方便大家的合作開發(fā)與降低業(yè)務之間的耦合度岸霹。
現(xiàn)在就和大家談談模塊化的交互問題疾层,首先看下模塊化的幾個優(yōu)勢。

模塊化的優(yōu)勢:

1贡避,結構清晰:業(yè)務獨立痛黎,代碼實現(xiàn)分離,不會攪在一起刮吧。
2,便于協(xié)作:每個開發(fā)同學只要自己負責的模塊井厌,沒有太多的耦合致讥。
3拄踪,便于維護:各模塊管理自己的代碼、布局惶桐、資源贿衍,主工程可以方便添加與移除救恨。
特點:高內聚、低耦合擎淤。

常見的模塊化實現(xiàn)方式有兩種:

1嘴拢、業(yè)務 Module 都放到同一個工程里寂纪。
2、每個業(yè)務 Module 都是一個獨立的工程孝冒。
如圖:


模塊都在同一個工程里

!

模塊的劃分:

模塊可分為多種類型庄涡,一般分為:三方的基礎 SDK (網(wǎng)絡請求搬设,地圖導航,推送等)迹鹅;自己平臺的通用功能(網(wǎng)絡請求的能力封裝斜棚、圖片加載能力封裝该窗、權限設置、UI組件等)义钉;
業(yè)務模塊的拆分(登錄捶闸、交易、會員删壮、硬件等)。


模塊分層

模塊間通信:

雖然功能已經按模塊拆分税灌,但是模塊間通信也是多種形勢菱涤,如果處理不好模塊之間耦合嚴重維護成本增大洛勉。
常見模塊問通信有:直接依賴坯认、事件或廣播通信、路由通信陋气、面向接口通信引润,下面就對比下幾種通信優(yōu)勢淳附。

二、實現(xiàn)方案

直接依賴:

直接依賴

這種方式實現(xiàn)簡單别凹,但是耦合太嚴重炉菲,不方便維護與開發(fā)坤溃,當工程逐漸增大模塊逐漸增多,依賴關系會非常復雜祠饺,不推薦這種方式汁政。

事件或廣播通信:

EventBus: 我們非常熟悉的事件總線型的通信框架缀旁,非常靈活诵棵,采用注解方式實現(xiàn)祝旷,但是難以追溯事件怀跛。

廣播: 安卓的四大組件之一柄冲,在一個模塊中發(fā)送廣播設置數(shù)據(jù),在另一個模塊中注冊廣播接收數(shù)據(jù)漓拾,使用廣播進行數(shù)據(jù)傳遞方式廣播相對于其他的方式而言消耗資源較多骇两。

總結: BroadcastReceiver姜盈、EventBus,非常靈活示血,模塊之間沒有任何的耦合难审,但是代碼的可讀性差亿絮,難以追溯事件,不是很推薦葱绒。

路由通信:

模塊與模塊之間不存在依賴關系斗锭,而是各自運作岖是,簡單的來說就是映射關系的路由通信实苞,也是目前比較主流的一種方案黔牵,比較常用的開源框架是阿里的ARouter爷肝。
ARouter典型應用
從外部URL映射到內部頁面灯抛,以及參數(shù)傳遞與解析
跨模塊頁面跳轉,模塊間解耦
攔截跳轉過程夹抗,處理登陸纵竖、埋點等邏輯
跨模塊API調用靡砌,通過控制反轉來做組件解耦

面向接口通信:

以上幾種方式只是簡單的介紹,下面就具體說下通過接口解耦通信的方式摆舟,首先先看幾個問題邓了。

什么是面向接口編程?
接口大家都很熟悉骗炉,這里所說的面向接口編程,并不只是所謂的 java 中的 interface厕鹃,而是指超類型剂碴,可以是接口也可以是抽象類轻专。

面向接口比面向對象編程是更先進一步編程思想,而是附屬于面向對象編程的體系催训,屬于其中一部分,它是面向對象編程體系中的思想精髓之一亚兄。面向接口編程它的核心思想是將抽象與實現(xiàn)分離采驻,從組件的級別來設計代碼挑宠,達到高內聚低耦合的目的颓影。面向接口編程方法是,先定義底層接口模塊碎浇,也就是 通信的協(xié)議與功能約定 奴璃,是提供方實現(xiàn)對應的功能與能力城豁。
在架構中層次分明,不需要關注具體實現(xiàn)雳旅,開發(fā)中可以通過接口快速制定協(xié)議攒盈,與提供能力api哎榴,對于上層通過接口顯露能力,對于下層只需要依賴接口層相當于依賴api迎变。

面向接口編程的好處衣形?
靈活性高沒有依賴具體的實體热凹,實現(xiàn)層可以任意的更改與切換。在模塊化中可以相互依賴service(接口層)或依賴多個纪铺。

在模塊化中的使用
下面對于接口(interface)或api層統(tǒng)稱為service,其含義為服務提供者突诬。

模塊獨立的工程結構

對于旺隙,每一個 module 都一個獨立的工程結構骏令,每個 module 都有自己的 Service ,來統(tǒng)一暴露當前 module 所擁有能力與向外提供的服務。
模塊在一起的工程結構

對于 module 是在同一個工程里的項目結構周拐,service 可以放到統(tǒng)一的一個 Module 下妥粟,我們統(tǒng)稱為 Mediator勾给,這樣做的目的是為了減少 Module 創(chuàng)建與維護锅知。假設你的工程有20個業(yè)務 Module 如果都同時增加一個 service 層就會造成 Module 數(shù)量翻一倍喉镰。由于這里存入的都一些接口類,也是每個業(yè)務 Module 向外提供的服務其體量不會太大侣姆,這里并只是一個建議并沒有標準的做法捺宗。

當然也有更復雜的設計,一個 Module 又分不同的 service 實現(xiàn)如圖长已,這里不在展開細說。


module 在分層的設計

實際工程中使用與設計

在實際項目中有很多項目都同時開發(fā)兩版本Pad與Phone康聂,有的是兩獨立的工程恬汁,有的是在同一個工程內用 flavor 切換不同的工程辜伟,下面我就以通過 flavor 切換的工程結構舉例。

先看下工程的包的結構圖:


flavor控制版本的工程結構

可以看到 module 結構是分為三個部分约巷,common, pad, phone, 如果每個service 都獨立將增加3倍的 Module 數(shù)量独郎。


通過共用 Module Mediator 統(tǒng)一管理 Service

使用一個 Mediator Module 統(tǒng)一管理這這些 service 就很好控制了 module 數(shù)量囚聚。

service 創(chuàng)建

在 module_mediator 業(yè)務 module 下 common,pad茁计、pone 下分別創(chuàng)建ICommonService, IService(pad), IService(phone)。
ICommonService:公共服務践剂。
IService(pad):pad服務并繼承CommonService馋评。
IService(phone):phone服務并繼承CommonService竣贪。


Service 關系圖

注:這里為什么不用,PadService與PhoneService匕争,是因為pad與phone版本同時只會存在一個爷耀,使用方只需要關心你提供的Service不用在區(qū)分版本,而且這里是一個繼承關系也可以獲取到共用的部分跑杭。

service 實現(xiàn)

依賴 Mediator :


添加依賴

在業(yè)務 common\pad\phone module 下分別實現(xiàn)德谅,ICommonService, Service(pad), IService(phone) ,在 common module 創(chuàng)建 CommonServiceImpl 實現(xiàn) ICommonService宅荤,在 pad冯键、phone module 分別創(chuàng)建 ServiceImpl 對應實現(xiàn) IService 并繼承與 CommonServiceImpl庸汗。


實現(xiàn)結構圖

service 注冊

注冊的方式有一般是通過代碼用去注冊改化,或通過注解進行注冊〕赂兀可以在 Application 注冊也可以在業(yè)務 Module 下自己注冊句旱,如果使用注解則可以自動注冊晰奖,具體要看項目怎樣實現(xiàn)。
例:


代碼注冊示例

注冊方法

解釋下 MediatorServiceFacator啃匿,它只是一個服務工廠也是一個接口類溯乒,作用是負責管理各業(yè)務方的 Service 主要功能是注冊與獲取 Service臊岸。上面的代碼就是往里注冊了一個會員的 Service。

可以看出這個函數(shù)只有兩個參數(shù)灯帮,一個是接口class一個是實現(xiàn)類class,第一個參數(shù)cls:它會作為 key 來使用钟哥,第二個參數(shù)implClass:它會作為 value 來使用腻贰。

service 使用

通過 MediatorServiceFacator 懶加載獲取service對象,如果業(yè)務方沒有注冊則獲取一個空的對象冀瓦。

注冊有 service 沒有使用時是不會創(chuàng)建的写烤,如果使用過則會緩存下來洲炊,下次調用則直接返回暂衡。(第一次是通過反射創(chuàng)建)

例:
1、在 mediator 模塊下會員 CommonService 中 定義了一個模糊查詢會員的方法撑毛。


在 common 定義一個查詢會員的方法

2代态、在會員模塊下 common 中實現(xiàn)了該功能疹吃。


實現(xiàn)查詢會員功能

3萨驶、在會員模塊下 pad 中繼承了這個實現(xiàn)腔呜。


繼承公共的實現(xiàn)

4核畴、在其他模塊 pad 下使用這個功能谤草。


調用查詢會員的方法

可以看到獲取 Service 只要傳對應接口就即可,對于使用方是不用關心實現(xiàn)方冀宴,在開發(fā)過程中只要先定義好接口温学,合作的同學就可以進入正常開發(fā)了。
細心的同學可以看出逃延,返回的數(shù)據(jù)類型也是一個接口類揽祥,為什么不直接返回一個普通 java 類呢?主要原因是通過接口方法達到雙方 api 約定紧帕,例如 getName() :String 方法是通過方法名返回值達到約定效果是嗜,這樣不依賴具體實現(xiàn)。

從上面的例子可以看出主要分為三個部分:
1站绪、定義接口恢准。
2馁筐、提供方實現(xiàn)接口坠非。
3、使用方都通過服務工廠獲取服務使用盟迟。
對于使用者來是很簡單的攒菠,不需要關心實現(xiàn)辖众,通過接口可以直接獲取到實現(xiàn)卓起,并且獲取到結果可以直接使用,不需要做序列化處理赵辕。

有了路由通信我們?yōu)槭裁催€使用面向接口編程既绩?

路由模式雖然很好的解決了耦合的問題,但他的方法調用都是靜態(tài)的还惠,對于傳參與返回值只能是基本類型饲握,如果是對象需要做序列化與反序列化處理,對性能有一定影響蚕键。
類似在調后臺接口一樣救欧,同時降低了代碼的可讀性, 對于 app 而言所有 Module 都是在同一個應用下锣光,沒有必要做這些序列化操作笆怠。

對于復雜業(yè)務不好處理蹬刷,例如一個業(yè)務需要多次通信,路由模式則不好處理搂漠,而通過接口通信則可以容易解決而克。
例如:
一個讀卡的操作,業(yè)務方需要對它有開啟充活、關閉映穗、暫停等多個狀態(tài)的操作宿接。通過接口則可以直接返回一個讀卡的 service 控制器睦霎, 這樣可以直接進行相應的控制操作蛤高。


返回一個接口控制器

從上面代碼中可以看出,上層回調結果的同時并回調了一個控制接口,這樣就提供使用方一個反向操作的能力喜庞。

三、總結

通過路由通信窄潭,可以很好的解決模塊間耦合,但拿不到對象無法持續(xù)交互幽污,并且需要序列化,而通過接口通信准潭,則很好地解決了這一點刑然,并且代碼可讀性比較高怔软。而接口通信會有一定的耦合性,也就是依賴了提供方的 service 層相當 api家坎,但對于收益來說還是值得的方式。

在架構模式中订框,沒有最好的模式只有比較合適自己項目的模式,希望大家都可以活學活用矛物,謝謝。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子浸锨,更是在濱河造成了極大的恐慌,老刑警劉巖冯凹,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浑劳,死亡現(xiàn)場離奇詭異,居然都是意外死亡鸽扁,警方通過查閱死者的電腦和手機躲雅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門慰于,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛆挫,你說我怎么就攤上這事璃吧∝迹” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長片仿。 經常有香客問我光督,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上张惹,老公的妹妹穿的比我還像新娘盾剩。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般粪摘。 火紅的嫁衣襯著肌膚如雪轩褐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天巢墅,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛匾竿,可吹牛的內容都是我干的昵慌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鹉梨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起疤孕,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤截亦,失蹤者是張志新(化名)和其女友劉穎却桶,沒想到半個月后嘁扼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡商虐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡温技,死狀恐怖,靈堂內的尸體忽然破棺而出套才,到底是詐尸還是另有隱情峰髓,我是刑警寧澤儿普,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布浪汪,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏谐鼎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一咐低、第九天 我趴在偏房一處隱蔽的房頂上張望福侈。 院中可真熱鬧,春花似錦卢未、人聲如沸肪凛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伟墙。三九已至,卻和暖如春滴铅,著一層夾襖步出監(jiān)牢的瞬間戳葵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工汉匙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拱烁,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓噩翠,卻偏偏與公主長得像邻梆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子绎秒,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354