?這些年又官,參與的項目大大小小應(yīng)該有六七個。所采用的項目架構(gòu)镣隶,也是從 MVC 到 MVP 极谊,后來使用 ReactNative 進(jìn)行跨平臺開發(fā),再到后來回到原生安岂,使用 MVVM轻猖。本節(jié),打算聊一聊我的項目架構(gòu)的演變之路域那。
MVC
?M, Model咙边,主要負(fù)責(zé)進(jìn)行數(shù)據(jù)訪問猜煮,產(chǎn)生數(shù)據(jù);C败许,Controller王带,主要負(fù)責(zé)對接 View 和 Model,將 Model 反映到 View 上市殷,或者響應(yīng) View 上的動作愕撰,修改 Model,處理業(yè)務(wù)醋寝;V搞挣,即 View,主要負(fù)責(zé) UI 渲染音羞。
?上圖來自維基百科囱桨。我們可以看到一個典型的 MVC 模式下的數(shù)據(jù)流向。上圖中黄选,View 監(jiān)聽 Model 的數(shù)據(jù)變化蝇摸,然后進(jìn)行 UPDATES 工作,這其中也會有業(yè)務(wù)邏輯處理办陷。事實上貌夕,有些時候我們還需要對 Model 層的數(shù)據(jù)做進(jìn)一步處理然后再做前端展示,這也是部分業(yè)務(wù)邏輯民镜。
?所謂架構(gòu)只是一種設(shè)計理念啡专,目的就是在于保持邏輯的清晰,面向改變易擴(kuò)展制圈,功能易復(fù)用们童。對于 MVC 模式而言,看上去各司其職鲸鹦,請求數(shù)據(jù)的產(chǎn)生數(shù)據(jù)慧库;負(fù)責(zé)邏輯的處理邏輯,負(fù)責(zé)渲染的進(jìn)行渲染馋嗜,清晰明了齐板。
?然而,View 層對 Model 有著很強的依賴葛菇。為了能夠使得 Model 發(fā)生的變化及時反映到到 View 上甘磨,View 需要注冊成為觀察者到 Model 上。鑒于這種關(guān)系眯停,View 济舆、 Model 需要互相持有對方的引用。
?首先莺债,這種相互持有引用會導(dǎo)致層次的獨立性滋觉、可重用性要降低一些签夭,而且這種行為也是危險的,暴露更多的能力給 View椎瘟,可能使得部分本應(yīng)在 Controller 處理的邏輯放在 View覆致,因為這樣做確實更加快捷方便。這樣做也會帶來一個很嚴(yán)重的問題:View 會客串 Controller 的角色肺蔚,從而越來越臃腫煌妈,解耦能力越來越弱。
MVP
?使用 MVC 沒多久宣羊,同事建議組長采用 MVP 開發(fā)模式璧诵,于是,就是這么快的就跳轉(zhuǎn)到了 MVP 的陣營仇冯。當(dāng)時最感興趣的還是這種架構(gòu)中突出的對接口的應(yīng)用之宿,面向接口的編程思想。
?面向接口的編程苛坚,實際上是 Java 開發(fā)一直所倡導(dǎo)的比被。優(yōu)勢在于解耦,降低依賴關(guān)系泼舱。但是也會讓開發(fā)工作更加復(fù)雜等缀。
?上圖同樣來自維基百科。相較于 MVC 模式娇昙,它切斷了 View 層和 Model 層的直連尺迂。Model 和 Presenter 之間, Presenter 和 View 之間相互暴露接口冒掌,并通過接口相互訪問噪裕,接口構(gòu)成了它們通信的通道。與 MVC 類似股毫, Modle 負(fù)責(zé)數(shù)據(jù)訪問和處理膳音;Presenter 像膠水一樣,把 Model 和 View 綁在一起铃诬,它主要處理業(yè)務(wù)邏輯祭陷,對 View 提供處理好的數(shù)據(jù),對 Model 請求數(shù)據(jù)氧急;View 處理 UI 渲染。
?后來的開發(fā)過程中毫深,很少使用 MVC吩坝,當(dāng)然并不是因為覺得它比 MVP 差。更多的哑蔫,自己是想增強接口使用的意識钉寝,以及對新事物的一種探索欲』∧牛現(xiàn)在想想,其實它們更多的是理念上的不同嵌纲,如果控制的足夠好俘枫,各有千秋吧。下面我們就來比較一下逮走。
MVC vs MVP
?這兩種結(jié)構(gòu)鸠蚪,都體現(xiàn)了良好的解耦理念。將一個需求拆分成數(shù)據(jù)訪問模塊师溅、UI渲染模塊茅信、業(yè)務(wù)處理模塊,相對獨立墓臭,分工明確蘸鲸,各謀其政。同時窿锉,各個模塊之間又可以在一定程度上相互組合酌摇,盡可能地進(jìn)行功能復(fù)用。但是嗡载,在具體使用上窑多,我覺得還是有一些偏好。
?保證結(jié)構(gòu)的清晰是一件非常重要的事鼻疮,對此怯伊,大多數(shù)情況下寧愿犧牲性能。這一點上我認(rèn)為 MVP 要比 MVC 做的好判沟,職責(zé)劃分的更加清晰耿芹。Activity 只負(fù)責(zé)渲染,很清爽挪哄;當(dāng)然吧秕,這就意味著更多的處理邏輯需要搬到 Presenter 中去;Model 只負(fù)責(zé)向 Presenter 提供數(shù)據(jù)支持迹炼。為了保證邏輯的清晰砸彬,整個過程卻會顯得復(fù)雜,有些地方甚至沒必要斯入。View 層明明只是需要改一下 Model 的數(shù)據(jù)砂碉,都需要 Presenter 代勞。顯然刻两,這種清晰性犧牲了高效增蹭。
?結(jié)構(gòu)上的清晰,職責(zé)上分工更加明確磅摹,更細(xì)滋迈,也應(yīng)該就意味著更好的復(fù)用性霎奢,更加靈活。但是饼灿,同樣這也未必總是需要的幕侠。如果一個需求交互不多,Presenter 可能就會非常小碍彭,又何必將一個文件能夠搞定的事一定要分成三個文件去完成晤硕?
MVVM
?MVVM 是由 MVP 演化而來的。我覺得它主要解決了 MVP 沒有很好解決的兩個問題:
- 對于 MVP 的 Presenter 層硕旗,由于要處理所有業(yè)務(wù)邏輯窗骑,又要完成 Model 和 View 的溝通,最終可能也會非常臃腫漆枚。
-
通常情況下创译,我們總是要通過 findViewById 找到控件,然后進(jìn)行數(shù)據(jù)填充墙基,如果一個頁面很復(fù)雜软族,需要填充的數(shù)據(jù)很多,這樣在 View 層會顯得很不優(yōu)雅残制。
?這樣立砸,就交給 MVVM 來解決吧。
MVVMPattern
?上圖(來自維基百科)中很好的解決了這兩個問題初茶。ViewModel 集合了 Presenter 的能力颗祝,同時兼顧了 View 需的數(shù)據(jù)基礎(chǔ)。它將數(shù)據(jù)直接綁定到 View上恼布,這種綁定是一種雙向綁定螺戳,即數(shù)據(jù)的變化會自動導(dǎo)致 UI 的刷新,而 UI 上的動作折汞,同樣會自動調(diào)用響應(yīng)的綁定的函數(shù)修改數(shù)據(jù)倔幼。
?Android 所提供的 DataBinding 技術(shù)很好的體現(xiàn)了這一點。之前翻譯過一篇官網(wǎng)上關(guān)于 DataBinding 的介紹爽待,感興趣的可以看一下∷鹜現(xiàn)在 View 層可以更加清爽,不用再為了填充數(shù)據(jù)而找出所有的 View鸟款,一個一個填充膏燃,而 View 也會由于某個用戶動作而自動回調(diào)修改數(shù)據(jù),這一切都是自動完成的何什。當(dāng)然组哩,有利必有弊,這種框架的使用,首先需要我們?nèi)チ私馑奶匦越矗欢易詣油瓿桑幢貢形覀兪謩油瓿尚矢呋舯龋喟霑奚糠中阅堋?/p>
小結(jié)
?架構(gòu)幕袱, 一種理念,一種思想悠瞬,一個工具们豌。它的目的,旨在幫助我們更好地面對浅妆、處理變化望迎;更加清晰地認(rèn)知我們正在做什么。
?工具是有了凌外,這只是一個基礎(chǔ)辩尊。更為關(guān)鍵的我覺得還是對這種工具的把控能力。因此康辑,也并非是說你使用了 MVVM 摄欲, 你的項目應(yīng)對變化的能力就一定會比 MVC 好。對于需求的理解疮薇,將需求進(jìn)行抽象的能力胸墙,以及對于技術(shù)扎實的能力,這些都將會對架構(gòu)的把控提出挑戰(zhàn)按咒。