在上篇文章里,我們對(duì)Google官方的TODO-MVP-Loaders做了分析狞悲,今天繼續(xù)探討另外一種官方實(shí)現(xiàn)撮抓,基于Clean架構(gòu)的MVP實(shí)現(xiàn)。
Clean架構(gòu)摇锋,如果從分層方式來(lái)看丹拯,主要涉及了一種“洋蔥式”的分層設(shè)計(jì),這些層次包括:UI框架層荸恕、Presenter層乖酬、Domain層、Entities層融求。
各層之間是單向的咬像、從外到內(nèi)的依賴關(guān)系,并且越往內(nèi)層,其實(shí)現(xiàn)越不依賴于具體的平臺(tái)框架施掏。更專業(yè)钮惠、更詳細(xì)的說(shuō)明,可直接閱讀Uncle Bob的文章:The Clean Architecture七芭。
這種架構(gòu)的好處有:
1素挽、當(dāng)UI相關(guān)代碼需要修改時(shí),對(duì)其他層不產(chǎn)生影響或者影響很少狸驳;
2预明、業(yè)務(wù)邏輯通過(guò)UseCase或者Interactor類封裝,方便擴(kuò)展維護(hù)耙箍;
3撰糠、可以靈活使用不同的數(shù)據(jù)庫(kù)方案,而不影響其他部分代碼辩昆;
4阅酪、方便單元測(cè)試,提前暴露問(wèn)題汁针。
上述分層方式與MVP的分層架構(gòu)有所不同术辐,但兩者可以結(jié)合起來(lái),發(fā)揮各自的優(yōu)點(diǎn)施无。我們來(lái)看TODO-MVP-Clean是如何實(shí)現(xiàn)的辉词。
這是Google官方網(wǎng)站上,對(duì)應(yīng)TODO-MVP-Clean實(shí)現(xiàn)的一幅圖猾骡。
從上圖可以看出瑞躺,相對(duì)于基礎(chǔ)實(shí)現(xiàn),主要是增加了Domain層兴想,包括與具體業(yè)務(wù)邏輯對(duì)應(yīng)的UseCase及其派生類幢哨。
在官方介紹里面,該實(shí)現(xiàn)從整體上被分為了3層:
Presentation Layer襟企,包括各種View嘱么、Presenter類;
Domain Layer顽悼,包括UseCase及其派生類曼振;
Data Layer,主要包括實(shí)現(xiàn)了TasksDataSource接口的TasksRepository類蔚龙。
其UML靜態(tài)結(jié)構(gòu)圖如下冰评。這里為了簡(jiǎn)潔,只選取了其中保存任務(wù)相關(guān)的靜態(tài)結(jié)構(gòu)進(jìn)行分析木羹,對(duì)于其他諸如獲取任務(wù)甲雅、刪除任務(wù)的結(jié)構(gòu)分析也類似解孙。
以新建任務(wù)時(shí)的保存操作為例,其UML動(dòng)態(tài)序列圖如下抛人。
結(jié)合序列圖弛姜,我們?cè)趨⒖荚搶?shí)現(xiàn)時(shí),可以關(guān)注如下幾點(diǎn)妖枚。
首先是業(yè)務(wù)邏輯相關(guān)調(diào)用廷臼。在Presenter中,原先基礎(chǔ)實(shí)現(xiàn)里面直接調(diào)用TaskRepository對(duì)象的地方绝页,在該實(shí)現(xiàn)中荠商,已經(jīng)改為通過(guò)UseCaseHandler調(diào)用,再由內(nèi)部的UseCaseThreadPoolScheduler調(diào)用SaveTask這個(gè)UseCase的具體實(shí)現(xiàn)续誉,最后通過(guò)TaskRepository的saveTask方法來(lái)完成整個(gè)操作莱没。
其次關(guān)注回調(diào)處理。在SaveTask里面酷鸦,保存成功后饰躲,會(huì)調(diào)用UseCaseHandler中的onSuccess回調(diào)函數(shù),再通過(guò)UseCaseThreadPoolScheduler觸發(fā)AddEditTaskPresenter中的回調(diào)井佑。這里和具體業(yè)務(wù)邏輯相關(guān)的地方属铁,分別在SaveTask眠寿、AddEditTaskPresenter中躬翁。
再次就是Domain層的UseCase里面模板參數(shù)的實(shí)現(xiàn)。還是以保存任務(wù)為例盯拱,在定義SaveTask類時(shí)盒发,需要根據(jù)具體業(yè)務(wù)(例如保存任務(wù)數(shù)據(jù)),專門定義內(nèi)部類狡逢,分別實(shí)現(xiàn)模板參數(shù)中UseCase.RequestValues和UseCase.ResponseValue這兩個(gè)接口宁舰。
另外,UseCaseThreadPoolScheduler里面的線程池設(shè)計(jì)奢浑,用于同時(shí)有多個(gè)UseCase需要執(zhí)行的場(chǎng)景蛮艰。這里還使用了單例模式,上述Scheduler所屬的UseCaseHandler對(duì)象為全局的單例對(duì)象雀彼。