動機
移動端應(yīng)用隨著硬件和平臺能力提升, 有了日趨復(fù)雜的趨勢. 而移動端的架構(gòu)演化也將
影響移動端架構(gòu)的一些要素有:
- 功能復(fù)雜程度, 常常來源于需求的復(fù)雜程度
- 平臺的能力, 現(xiàn)代移動端操作系統(tǒng)的平臺能力日趨強大
- 開發(fā)團隊的規(guī)模
- 開發(fā)者的技術(shù)棧, 依賴于流行的開發(fā)技術(shù)
本文的動機主要是通過簡單介紹集中移動端比較常見的框架, 來幫助讀者了解并可以應(yīng)用到自己的項目中.
MVC
Model-View-Controller結(jié)構(gòu)應(yīng)該是非常經(jīng)典且古老的架構(gòu)了. 百度百科上的圖示有非常詳細(xì)的說明:

在阮一峰的網(wǎng)站上, 可以找到包含用戶交互的完成圖示:

這里有一個需要注意的地方: View和Model是可以互相訪問的.
MVP

Model-View-Presenter是MVC進化而來的. 主要功能是隔離了View和Model層,由于View和Model層可以互訪, 帶來了耦合.
將MVC中的Controller替換成Presenter, 隔離了Model和View, 就成為了我們看到的MVP模式.包含了用戶交互的圖示:

這里我們可以舉個例子, 一家便利店:
- Model相當(dāng)于倉庫
- View相當(dāng)于貨架上面擺滿了商品
- Presenter相當(dāng)于店長,理貨員和售貨員
這里View也叫做被動視圖, 沒有任何的主動性. 在實際開發(fā)中, 系統(tǒng)負(fù)責(zé)交互的模塊充當(dāng)著上圖中用戶的角色.
MVVM

Model-View-ViewModel是MVP的一個變種. 基本上可以理解為將MVP的Presenter替代為ViewModel.同時引入了一個DataBinding的概念.
- Binder(DataBinding)是MVVM模式中隱含的一個概念, 是View和ViewModel存在的一種雙向綁定: View中的變化會自動反應(yīng)在ViewModel中, 反之亦然.
小結(jié)
在看過MVC, MVP, MVVM后, 我們簡單小結(jié)一下. 這三種模式都是解答如何拆分一個應(yīng)用程序這個問題的. 在實際使用中, 主要的關(guān)注點是如何拆分系統(tǒng)中交互邏輯 "最重" 的部分. 比如在Android上, 我們的關(guān)注點就是如何拆分Activity(Fragment), 在iOS上,則是如何拆分ViewController.
- 在Android上, 通常使用MVP, 將Activity拆分成MVP中的"View"和"Presenter", 同時"Presenter"中加入能夠和Model交互的邏輯處理.
- 在iOS上, 通常使用MVVM, 將ViewController拆分成"View"和"ViewModel", 在"View"中綁定"ViewModel"中的屬性.
Clean Architecture

Clean Architecture的結(jié)構(gòu)很像一顆洋蔥, 其分層原則: 里面的層是永遠(yuǎn)不知道外層的.
需要先理解幾個概念:
- Entities
應(yīng)用程序的業(yè)務(wù)對象 - Use Cases(Interactors)
業(yè)務(wù)邏輯 - Controllers/Presenters(Interface Adapters)
控制層, 決定何種輸入需要處理 - External Infertfaces(Frameworks and Drivers)
外界環(huán)境的抽象, 比如說UI, frameworks, 數(shù)據(jù), 網(wǎng)絡(luò)連接等
一個比較直觀的圖示如下:

還可以結(jié)合下圖理解:

可以參考下面兩個Repo上的代碼進行理解:
- Android-CleanArchitecture
-
android-clean-architecture-boilerplate
還有兩篇文章幫助理解: - Clean Architecture: Use case containing the presenter or returning data?
兩個實例代碼其實各有不同, 而且Clean架構(gòu)其實有MVP和MVVM的影子, 但是一個核心點在于: 數(shù)據(jù)的流動和層級間的依賴是單項的, 也就是說, 在Clean架構(gòu)中, 不存在回環(huán)的情況, 這一點也是這個架構(gòu)的優(yōu)越之處.
VIPER

- View
用戶的交互傳給Presenter, 根據(jù)Presenter的要求展示畫面 - Interactor
業(yè)務(wù)邏輯 - Presenter
負(fù)責(zé)從Interactor處取得數(shù)據(jù)給View展示, 同時負(fù)責(zé)通知Router畫面跳轉(zhuǎn) - Entity
Interactor所使用的數(shù)據(jù)對象 - Router
畫面跳轉(zhuǎn)和展示邏輯, 在實際實現(xiàn)中, Router常常還承擔(dān)著創(chuàng)建View, Presenter和Interactor.
總結(jié)
綜上可以看出, 所有的架構(gòu)設(shè)計都在完成一件事:
合理的分配各個組件的負(fù)擔(dān), 避免過輕或者過重. 同時避免耦合, 使得模塊或者層級內(nèi)部就可以自成體系, 減少對外部的依賴.
移動應(yīng)用架構(gòu)的演進過程就是根據(jù)研發(fā)團隊的人員架構(gòu)選擇一個合理的,能夠有效協(xié)作模式的過程. 隨著團隊架構(gòu)變化, 可能程序架構(gòu)也需要隨之升級變化.