僅需6步,教你輕易撕掉app開發框架的神祕面紗(2):MVP比MVC更好嗎

對於程序框架的選擇,由於android天然的MVC,本來不需要另外設計直接使用即可。但是我更加鍾情於MVP模式,對於其將ui完全與業務邏輯分離的思路很贊同。

那麼什麼是業務邏輯?個人認爲,對數據(即MVC中的M)的處理即爲業務邏輯,數據主要有3個來源:

  • 服務端返回的數據
  • 從其它途徑傳入的數據
  • 自己定義的數據(需要傳遞時)。

實際操作中,指不定哪天老闆說,啊這個頁面顏色太淡了,這個頁面按鈕太多了,另一個頁面文字換成圖片。

怎麼辦?美術負責人說,我做兩個版本吧,先上線測試,看看哪個效果好就用哪個。

你該怎麼做?

  • 反駁老闆,說他是錯的,然後第二天你就可以去找一份新工作了。本文到此結束。
  • 不反駁老闆,往下看。

既然選擇忍辱負重,那麼就要努力想解決方案。

如果使用MVC模式,你需要複製你的Activity,建立新的文件 Activity2,然後刪除頁面相關代碼,添加新的頁面代碼。

這樣做可以完成任務,但是有2方面的問題:

  • 修改頁面時,其中混雜的業務邏輯就會從中作梗,因爲某些業務邏輯會跟view操作寫在同一個函數中。因此在修改view的時候,很容易就修改/刪除了某些業務邏輯相關代碼。這樣,等你寫完了之後恐怕連你自己都沒法保證沒有寫錯。後續就是大量的測試和代碼對比。如果明天老闆就要驗收,或者讓你改第三次怎麼辦?
  • 業務邏輯冗餘,你會發現兩個activity中有着大量相同的代碼。一旦某個業務邏輯需要改變,比如接口名稱變化,你需要修改兩個地方。

這時候你可能會想,我把業務邏輯封裝成一個個函數,給這些函數添加適當的參數和返回值,然後提取到另一個類中,比如就叫做ActivityDataHandler。來表示Activity業務邏輯的處理。

這樣問題不就解決了嗎!

  • 首先業務邏輯不會跟頁面混雜,只要看到ActivityDataHandler的實例就知道是業務邏輯了。
  • 其次不會有2處業務邏輯了。因爲都封裝到ActivityDataHandler中了。

但是問題又來了,如果說對數據的修改僅僅是來自頁面操作,上面這樣做是可以解決問題的。

如果數據的修改不是通過頁面操作進行的呢?比如某個接口調用之後,數據理應傳給ActivityDataHandler,而不是Activity。

Activity怎麼才能知道數據回來了,進而刷新頁面?

這時候你明白了,需要在ActivityDataHandler中添加一個引用,指向Activity,這樣每次ActivityDataHandler中的數據變化都可以直接調用activity中的方法了。

嗯不錯,問題似乎解決了。但是你還是忽略了一個問題,那就是Activity不止一個。

在這種情況下你需要在ActivityDataHandler中添加多個Activity的引用,然後在數據變化時,用if-else來判斷調用不同activity的不同方法。

這樣上面的問題是解決了,但是又引入了新的問題。ActivityDataHandler中添加多個Activity的引用,這本身就是一個冗餘,從設計模式角度來講,如果一個兩個還好說,如果需要添加10000個則需要修改ActivityDataHandler10000次,這違反了設計模式中的:開閉原則。

所以這時候你會想,我把Activity中涉及因爲數據的改變而需要修改頁面組件的部分,封裝成不同的方法,然後把這些不同的方法提取到一個接口中,IActivity。這樣每次新加入一個Activity只需要繼承IActivity,然後把IActivity的引用傳給ActivityDataHandler即可。

這樣ActivityDataHandler只需要引用一個IActivity就夠了,不用關心具體是哪個activity,這體現了設計模式中的依賴倒轉原則:只針對接口來編程。
嗯,這時候你舒了一口氣,說,這下沒問題了吧!哈哈,確實,表面上看似乎沒問題,很完美。

但是別高興的太早,因爲此時老闆和美術人員可能不找你麻煩了。但是後端程序和產品經理又向你走來。

後端程序說,我這個接口不太穩定,因爲網頁端需要測試,所以可能某個頁面要寫2套接口,你這邊最好兼容一下,我給你個參數,你用這個參數來判斷調用哪套接口。。

產品經理說,這個頁面跳轉回來後,我不確定應該顯示什麼內容,到時候要具體根據統計數據來看,所以我希望,一部分用戶跳轉回來後顯示真數據,另一部分用戶則顯示假數據。。

這時候你說,沒問題,我在接口調用的地方加一個if-else來判斷調哪個接口。然後,在頁面跳轉後數據修改這裏也加一個if-else,判斷這個用戶類型,然後給返回不同的數據。

然後你猶豫了一下,覺得似乎哪裏不對勁。回頭看了看上面Activity修改時所遇到的問題,於是明白了問題所在:違反開閉原則。

找到問題就簡單了,解決方法同上面解決多個Activity引用的方法一致:建立IActivityDataHandler,爲不同的邏輯添加多個ActivityDataHandler。然後Activity中添加IActivityDataHandler引用。

問題至此完美解決。

Activity,IActivity,ActivityDataHandler,IActivityDataHandler。這四個類及上述分析,就構成了MVP模式。

如此看來,MVP確實是個不錯的框架,解決了不少問題,但是在我看來,它實踐起來還是有一定的困難的。

MVP其實就是把MVC中的C再次拆分爲V和P的一個框架。

主要問題有3個:

  1. 做功能的程序員每寫一個activity需要寫多個文件一個Activity,一個Presenter,一個IActivity的接口,一個IPresenter的接口,麻煩,對於一個快速迭代的項目(已知不會有太多的變化和修改)來說不是很輕便。而且文件一多,有些思維不連貫的程序員就會混亂。
  2. Activity和Presenter任務不明確,有時需要2個類同時處理的某些操作,會令程序員造成迷惑。
  3. Activity和Presenter相互引用,耦合很重。其實這一點是難以避免的。

後續會介紹我是如何搭建具有個人特色的MVP模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章