自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你真的理解了MVC, MVP, MVVM嗎?

開發(fā) 開發(fā)工具
準備寫這篇文章的時候 , 我自認為對MVC已經(jīng)有深刻理解了,可是畫圖的時候發(fā)現(xiàn),理解還是有漏洞,于是又閱讀,思考,整理,加深了理解, 寫了這篇文章, 估計還有漏洞,歡迎討論。

前言: 準備寫這篇文章的時候 , 我自認為對MVC已經(jīng)有深刻理解了,可是畫圖的時候發(fā)現(xiàn),理解還是有漏洞,于是又閱讀,思考,整理,加深了理解, 寫了這篇文章, 估計還有漏洞,歡迎討論。

這再一次說明了寫作的好處: 很多時候自以為理解了,實際上腦海中有很多想當然的假設(shè),寫作會把這些假設(shè)給暴露出來。

大概是二三十年前, 人類逐漸從命令行界面時代走出來,進化到了GUI時代。

注: GUI(Graphic User Interface),即圖形用戶接口。

(一個命令行程序)

(一個帶有圖形界面的桌面應用程序 ,自己畫的,有點丑啊)

每當人類努力地開發(fā)新的桌面GUI程序的時候, 至少要搞定下面幾類工作:

1. 界面(以及界面中元素的)布局。

這是一件挺費勁的工作, 要盡可能地美觀漂亮,要不然就賣不出去。

2. 界面上有些“邏輯”需要處理

比如上圖中那個薪水計算程序,“計算” 按鈕默認是灰色的, 不能點擊,用戶輸入了稅前收入以后, “計算”按鈕就會被激活,表示計算了。

3. 所謂的業(yè)務邏輯。

用戶點擊了“計算”按鈕以后,計算五險一金,個人所得稅和稅后收入。

這三者攪在一起,讓程序代碼凌亂不堪,稍微復雜點兒的程序就長達幾千行, 不斷地挑戰(zhàn)著程序員的底線,修改別人的代碼,添加新的功能要比從頭寫難好多倍!

大家都在泥潭中掙扎。

桌面應用程序的 MVC

程序越來越復雜,Bug越來越多,沒辦法, 大家只好去求編程上帝。

上帝說: 想從困境中走出來,一定要實現(xiàn)關(guān)注點分離(Separation of concerns)。

沒人能夠理解。

上帝解釋道:“ 你們?nèi)四X同時能處理的東西是有限的, 所以要把一個大系統(tǒng)給分解,變成幾個相對獨立的部分,這樣我們的大腦每次只關(guān)注某一方面,暫時忽略其他的,就能夠掌控了。”

沒人知道該怎么分解。

上帝只好想了一個辦法, 把關(guān)注點分離的理論給具體化,這個辦法就是MVC。

上帝告訴人類:

M 表示 Model , 專門用來處理業(yè)務邏輯,不干別的事情。

例如在那個薪水計算系統(tǒng)中。計算一個人的薪水,五險一金,個人所得稅等等。

V 表示View, 專注頁面布局和數(shù)據(jù)顯示。

例如把Button放置到某個位置,把總收入顯示到一個文本框,把稅金顯示到另外一個地方。

C 表示Controller  翻譯用戶的輸入,操作模型和視圖。

例如,用戶在界面點擊了一個“計算”的按鈕,View 把計算的請求傳遞給Controller (很明顯View需要知道Controller,換句話說,需要持有Controller的實例),Controller找到或者創(chuàng)建Model,執(zhí)行業(yè)務邏輯:計算薪水。

計算的結(jié)果該怎么展示呢?  人類問道。

上帝胸有成竹: 可以讓Model 去通知View。

Model需要持有View的實例(當然也可以通過觀察者模式),調(diào)用View對應的方法。

例如: View中可能有一個onResult的方法, 讓Model去調(diào)用,在調(diào)用的時候把一個參數(shù)對象Salary傳遞過來,不就可以展示數(shù)據(jù)了嗎?

  1. // View的方法,被Model調(diào)用:  
  2. public void onResult(Salary salary){    
  3.       //把個人所得稅(salary.getTax()) 展示到一個文本框 
  4.       //把凈收入(salary.getNetPay()) 展示到另外一個文本框 
  5.       ...... 

畫成流程圖的話是這個樣子:

大家都覺得MVC大法好,紛紛開始使用。

MVP

時間久了以后,人類就覺得不爽了,因為在這個MVC中,依賴太多:

View 依賴Controller和Model

Controller依賴View和Model

Model 和View的關(guān)系雖然很弱, 但是也需要某種方式來通知View進行數(shù)據(jù)更新。

人類說:“他們之間的耦合還是挺緊密的啊,親愛的上帝,能不能改改?”

上帝覺的人類還是挺有上進心的,決定繼續(xù)施以援手: “這樣吧, 可以改變一下Controller, 把Model和View完全隔離開,讓他們單獨變化。”

上帝把Controller 改了個名稱,叫做Presenter, 把整體命名為MVP。

在MVP當中,View只知道Presenter, 不知道Model 。

計算流程和MVC差不多,用戶點擊了“計算薪水”按鈕, View去調(diào)用Presenter, Presenter操作Model , Model 中進行業(yè)務計算。 關(guān)鍵點是,Presenter去更新View。

  1. //Presenter 的方法,被View調(diào)用 
  2. public void calculateSalary(){ 
  3.     //調(diào)用Model計算薪水 
  4.     view.showTax(xxx);    // 調(diào)用View顯示所得稅 
  5.     view.showNetPay(xxxx);//  調(diào)用View凈收入 
  6.     ...... 

但是Presenter還是需要調(diào)用View的方法,也就是說Presenter對View有依賴,這樣Presenter就沒辦法單獨做單元測試,非得等到界面做好以后才行。

于是上帝又做了一點改進,讓View層提取出接口,Presenter只依賴這個接口。

這樣Presenter不用依賴真正的界面就可以測試了,并且也增加了復用性,只要View實現(xiàn)了那個接口,Presenter就可以大發(fā)神威。

MVVM

使用了一段時間MVP以后,永不滿足的人類又覺得不爽了, 因為讓Presenter調(diào)用View的方法去設(shè)置界面,仍然需要大量的、煩人的代碼,這實在是一件不舒服的事情。

人類突發(fā)奇想: 能不能告訴View一個數(shù)據(jù)結(jié)構(gòu),然后View就能根據(jù)這個數(shù)據(jù)結(jié)構(gòu)的變化而自動隨之變化呢?

上帝看到人類思考了,表示了贊賞。

他說,我來送你們一個叫做ViewModel的東西,它可以和View層綁定。 ViewModel的變化,View立刻就會變化。

人類問: ViewModel? 里邊有什么東西?

上帝說: 拿你們的薪水計算為例, ViewModel 差不多這樣:

  1. public class SalaryViewModel{ 
  2.     String grossSalary;  //稅前收入,和View中的相關(guān)字段對應 
  3.     String netSalary;    //凈收入,和View中的相關(guān)字段對應 
  4.     String tax;          //個人所得稅,和View中的相關(guān)字段對應 
  5.     ......  
  6.     boolean  isCalculating;  // 一個標志位,表示正在計算  
  7.     String errMsg;           // 如果出錯的話,記錄出錯消息。 

當用戶在界面上點擊“計算”按鈕的時候, 你們需要設(shè)置一個SalaryViewModel中的標志位:

salaryViewModel.isCalculating = true;

這樣View 中就可以自動給用戶展示一個消息:“正在計算....”

當薪水計算完成的時候, 如果沒有錯誤,SalaryViewModel 中g(shù)rossSalary, netSalary,tax等屬性就有了值。 與此同時View 中對應的內(nèi)容也會更新, 不用你們手工去設(shè)置, 很方便吧?

如果計算過程出錯, SalaryViewModel 的errMsg 會保存出錯消息, 同樣,View中會自動把這個錯誤消息給顯示出來, 很智能吧?

人類說:“怎么可能這么智能呢? 這里的ViewModel 好像和View沒有什么關(guān)系??? 到底該怎么綁定啊??。?!”

上帝笑了: 你們可以開發(fā)一個框架嘛? 讓兩者綁定起來不就行了?

人類沒有辦法,只好自己動手。

(注:實際上微軟的WPF和Silverlight,  Android等框架和系統(tǒng)都可以實現(xiàn)View和ViewModel之間的映射和綁定)

Web應用程序的MVC

時間過得飛快,人類發(fā)明了互聯(lián)網(wǎng),Web應用程序如雨后春筍般崛起,B/S(瀏覽器-服務器)開始大行其道。

用戶通過瀏覽器發(fā)出GET,POST請求,服務器端進行處理,處理完以后生成HTML給瀏覽器。

無論什么操作,都是對服務器端URL的訪問。

人類突然發(fā)現(xiàn),整個編程模型發(fā)生了巨變, 不能簡單地套用原來的MVC和MVP了。

如果把HTML頁面比作原來桌面應用程序的View, 服務器無論是Controller還是Model都是無法遠程遙控這個View進行處理的。

人類這一次沒有去請教上帝,自己嘗試對MVC進行改良,其中有個叫Rod Johnson 帶領(lǐng)一幫人搞出的SpringMVC很成功。

不像桌面應用的MVC, 這里的Model沒法給View 發(fā)通知。

也不像MVP, 這里的Controller 也不會調(diào)用View的方法來設(shè)置界面。

實際上Controller 會選擇一個View, 然后把模型數(shù)據(jù)“丟過去”渲染。

原來的View 變成了 View Template(例如JSP , Velocity等等), 經(jīng)過渲染后變成HTML發(fā)給瀏覽器展示給用戶。

有人把這種MVC稱為 基于Web的 MVC,以便和之前的MVC區(qū)別開來。

前后端的分離

人類早期的B/S應用程序中, 每次訪問服務器端, HTML就會整體發(fā)給瀏覽器,即所謂的整體刷新。

后來人類發(fā)明了AJAX, 可以做到局部刷新。

于是瀏覽器端的應用變得越來越復雜,再后來人類竟然發(fā)明了Web上的SPA(單頁應用程序),用起來的體驗和最初的桌面應用程序越來越像。

人類發(fā)現(xiàn),那些MVC, MVVM之類的模式完全可以用到瀏覽器端嘛!

例如在瀏覽器端使用MVVM , 在服務器端可以使用MVC, 兩者結(jié)合起來:

前端和后端成功地分家了 !

【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請通過作者微信公眾號coderising獲取授權(quán)】

戳這里,看該作者更多好文

 

責任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2017-04-01 08:30:00

MVCMVPMVVM

2017-03-31 20:45:41

MVCMVPMVVM

2019-09-11 08:52:24

MVCMVPMVVM

2021-04-23 07:27:31

內(nèi)存分配CPU

2022-03-27 09:06:25

vuexActionsMutations

2024-03-15 08:23:26

異步編程函數(shù)

2018-08-20 08:30:05

Kafka架構(gòu)系統(tǒng)

2018-11-20 09:37:19

Java內(nèi)存模型

2014-03-17 11:05:00

ScriptCode Blocks

2019-12-26 09:15:44

網(wǎng)絡IOLinux

2023-12-14 12:55:41

Pythondel語句

2021-09-08 07:49:35

Dubbo連接控制

2019-10-30 14:58:45

MVCAndroid表現(xiàn)層

2012-11-30 11:19:02

JavaScript

2023-04-11 07:50:27

軟件架構(gòu)設(shè)計

2018-10-29 11:41:22

架構(gòu)MVCAndroid

2023-10-20 13:21:55

軟件設(shè)計模式架構(gòu)

2022-01-05 12:03:48

MySQL索引數(shù)據(jù)

2018-07-05 14:25:01

TCP握手原理

2022-05-03 00:03:11

狀態(tài)管理前端開發(fā)
點贊
收藏

51CTO技術(shù)棧公眾號