寫在前面
筆者第一次接觸 MVC 是在 java 中,不是 ssh 之類的大家伙,只是單純的分層開發,為了代碼結構更清晰
-
V(View)在 java 中可以是 swt, swing 做出的 GUI,當然,也可以是 jsp 生成的頁面
View 是單純的界面,負責以友好的形式展示數據給用戶
-
M(Model)可以是純粹的 Java Bean(傻豆豆,只有自定義數據結構和 getter/setter),也可以帶點數據校驗邏輯
還有把數據校驗邏輯放在 V 或者 C 裡面的,取決於具體場景,比如 jsp 應用把數據校驗邏輯放在 V 裡比較合適,可以減少請求
-
C(Controller)是業務邏輯聚集的一層,所有重要業務邏輯都在 C 裡面
C 負責接收 V 傳過來的用戶輸入,處理完畢後更新 M,M 再通知 V 更新,可以一個 V 對應(依賴)一個 C,也可以多個 V 對應 1 個 C(多個頁面的業務邏輯基本相同的話),但 1 個 V 不應該對應多個 C,因為這種依賴關係就是緊耦合了;M 和 V 的對應關係取決於實現方式,是經典觀察者模式還是發布/訂閱模式,前者 M 直接通知 V 更新,後者 M 只能通過 C 更新 V
後來發現有些邏輯放哪裡都不合適,比如數據庫操作(放 C 裡?)、配置數據/常量(放 V 裡?),於是新增了 Core 放常量、DAO 層放數據庫操作,都算 C 的輔助層
MVP 和 MVVM 的理念與這個不同,不是多一層少一層,而是對層的職能做了重新劃分,當然,重新劃分之後也添了其它輔助層
一.MVC
從輸入到輸出,數據流(勉強算數據流圖吧,阮把這個叫通信方式圖)如下:
[caption id="attachment_730" align="alignnone" width="889"]
MVC 数据流 [/caption]
注意:不是依賴圖。因為從依賴關係上看,M 和 V 是觀察者模式關係,應該是 V 依賴 M(Observer 知道 Subject 的存在及其公開的接口),M 不依賴 V(Subject 不知道誰關注了它,也不在乎都是些誰)。而從交互關係(數據流)上看,M 更新了 V(Subject 變了,會自動通知所有 Observer),V 沒有辦法直接更新 M。
依賴關係取決於具體實現,個人認為去糾結 Trygve Reenskaug 最初的實現沒有任何意義,所以依賴關係圖是畫不出來的,而且多年以後上面的數據流圖可能也是錯的,從最初的 C 接收用戶輸入,到現在的 V 也能接收,以後的變化誰知道呢?
(八卦:這也就是 winter 和阮的分歧所在,阮眼中的 MVC 是廣義的,是一種分層思想;而 winter 認為 MVC 就是 79 年的東西,其它的通通不能算 MVC。。。兩篇博文在底部參考資料中都列出來了,有興趣可以去瞅瞅)
(題外話:1979 年 Trygve Reenskaug 提出了 MVC,這個據說是正版,當時用戶輸入只能由 C 獲取,V 的功能及其弱,連輸入框上的光標都是 C 控制 V 繪製的,所以規定 C 只能存在一個,所有邏輯都必須流經 C,便於控制繁瑣的界面展示。而現在用戶輸入可以由 V 直接獲取,繪製光標等工作由操作系統自動完成,再拘泥於 C 只能存在一個就是徹頭徹尾的傻了)
Backbone.js
backbone 是前端 MVC 的框架範例,提供了 MVC 實現以及基本工具,自由度很大,實際應用中需要組合其它工具,比如 underscore、jQuery/zepto 是必需品
Backbone 是脊椎,表示只提供了最關鍵的框架實現,其餘部分都是非常自由的,關於 Backbone 的更多信息,請查看底部參考資料
二.MVP
最初的 MVP 圖示如下:
[caption id="attachment_731" align="alignnone" width="690"]
mvp[/caption]
與 MVC 相比,最大的區別不是 C 改名成 P(Presenter)了,也不是多的一條 M 到 V 的線,等下,不是觀察者模式嗎?怎麼 M 能直接訪問 V 了(Subject 能直接訪問 Observer 了)?待會兒再議。最重要的區別是P 不是單一的對象,而是圖中的 interactor, command 以及 selection 合起來叫做 P,也就是說 P 是不存在的,P 被分解成「interactor, command 以及 selection」了
因為在本來 M 和 V 的觀察者關係下,V 無法直接訪問 M,只能靠 C 傳遞,用著不爽(可能是效率或者易用性上的不爽),然後決定增強 V,讓 V 可以直接訪問 M(V 能接收用戶輸入也算是增強,因為最初的 MVC 只有 C 能接收用戶輸入,用戶在直接和 C 交互,光標、輸入文字什麼的都是 C 控制 V 顯示的)。然後把 C 改名為 P,以區別 MVC,其實叫 M(胖 V)C 也行,V 變厚了,C 就變薄了(簡單的數據顯示交給 V 了,直接獲取 M 的數據顯示出來(數據與視圖綁定?),當然,從上圖可以看出 V 只能讀 M,寫還是要通過 C 的),所以有人說 P 是一種 C,確切地說是更薄的 C
MVP 沒有合適的範例框架,因為大家對 MVP 的理解存在爭議。有的文章說 P 是增強的 V,還有說 P 裡面放的都是展示邏輯。。。那麼業務邏輯放哪裡?不能單單從 Presenter 字面意思上理解,想當然地去解釋
(MVP 是 1996 年提出的,因為有人覺得 1979 年的 MVC 已經不合適了,MVC 的理念當然還存在,只是最初死板的規則,比如 C 只有一個,只有 C 能獲取用戶輸入等觀念已經過時了,MVP 本身可能也只是過渡的產物���有用的只是背後的理念,比如分層開發、模塊化、事件驅動等等)
三.MVVM
MVVM 是微軟推出 WPF 時提出的模式,WPF 的特點是強大的控件,比如 DataGrid 可以直接與數據表綁定,極大地減少了簡單數據表展示的工作量。wpf 的 View 是用 XAML 定義的,控件的基本功能,比如輸入數據校驗,通過簡單的 XAML 配置就可以實現了,這其實就是 MVVM 最大的特點:V 與 M 的雙向綁定
MVVM 的好處是把 V 進一步分離,甚至 V 是用另一種語言(XAML)描述的,這樣就極大地增強了控件的可複用性,直接把上一個項目裡自定義控件的 XAML 代碼拿過來就可以用,而不用從原項目小心翼翼地剝離邏輯代碼
winter 給出的圖示如下:
[caption id="attachment_732" align="alignnone" width="690"]
mvvm[/caption]
也就是說,MVVM 裡的 V 是一個很強大、很完善、很厚的 V,因為這個 V = V+ C + E。至於數據綁定,從使用的角度看是 V 和 M 綁定了,比如 TextBox 的值會自動與 Model 數據同步。從上圖看是 V 和 VM 之間的數據綁定,VM 可以通過「命令」來操作 V,比如 xx.close() 之類的,更詳細的解釋如下:
如何呈現是 view 的事,調用方只用給 view 一個 data,view 就只負責這個 data 的顯示,調用者不用管 view 如何顯示,只負責將 data 傳遞,view 也不用管數據從何而來,只要將 data 以自己的方式呈現,並且時刻關注 data 的變化如何反映到 view 上來就好。
而雙向綁定,則是一個附加產品,畢竟只有像 textbox,form 等會改變數據的 UI 不多,大部分 UI 都只是單向的呈現數據而已。不過有雙向綁定在,則可以將 view 和調用方分離得更徹底,即獲取數據不必在意特別的 view,如一個日期是用戶在 textbox 中輸入,還是用 calendar 選取的無關緊要,因為那是 view 設計和安排的事。
Angular.js
Angular 的 MVVM 幾乎是公認的,MVVM 的特點就是重,wpf 好用是因為提供了一整套強大的常用控件,可想而知
關於 Angular 的更多信息請查看 Angular 官網,Angular 是 Google 做的,或許是 MVC 的發展方向
四.MV*框架的選擇
不建議直接將業務庫框架直接取來使用,更不建議使用過重的業務框架,最好是能明白框架想要解決的問題,與自己項目的實際需求,自己造輪子知根知底。
(引自 淺談移動前端的最佳實踐)
這句話應該很在理,有創業公司的朋友說公司要求用 Angular,沒有調研,沒有討論,就是要用。為什麼?火唄,合適不合適好用不好用都不重要
自己的內部框架當然是量體裁衣,出了問題有人去解決,不用去搜尋解決方案、不好用可以自己改,改得好可以直接擴展進去、嫌太大可以清理一下,把不常用的部分提出來作為可選模塊。。。自己的肯定要比別人的用著舒服,哪裡不爽改哪裡,比如$()的問題,應該根據業務情景好好選選,看document.querySelector 能否滿足需求,不行再看 zepto 的兼容性夠不夠,實在不行才用 jQuery
五.為什麼要了解 MV*
更糟糕的是,今天無數經過演繹的 MVC 實現(如 backbone)和科普文,要麼是原本作者概念已經很混亂,摻雜私貨,要麼為了適配現代的標記語言和控件模式,自己修改了經典 MVC 中的一些概念和耦合關係。實際上今天 MVC 已經沒法作為一種交流的標準詞彙了。
花時間了解 MV就是為了能夠聽懂別人在說什麼,但如上面所說,MVC 已經不是同行間能秒懂的那種標準詞彙了,對與錯可能不重要,如果非要糾結就得去讀 N 篇論文,找到 MV最初的實現理念,但沒必要這樣做了,因為 winter 幫我們做過了,最初的實現是一個參照點,接觸其它 MV*實現時可以對比理解,但不要糾結對錯,好用實用就行
參考資料
-
Backbone 源碼分析-Backbone 架構 + 流程圖:backbone 源碼分析
-
Backbone 源碼分析-JSMVC:backbone 與 MVC
-
同作為 JavaScript MVC 框架,Backbone 和 AngularJS 各有什麼優缺點?:backbone 與 angular
暫無評論,快來發表你的看法吧