http://damoqiongqiu./blog/1949256 ---比較Backbone和Ext4.x在MVC實現(xiàn)上的差異 前言圣人云:不想做媽咪的小姐不是好碼農(nóng)。 每一個碼農(nóng)的心中都有一個終極理想,那就是有一天不用再Coding。 在成為媽咪的道路上,“設(shè)計模式”被認為是一項必備的技能。 因此,經(jīng)常有濕主會問小僧這樣一個問題:為什么MVC不是一種設(shè)計模式呢? 對于這樣naive的問題,小僧向來是嗤之以鼻的,你們啊!圖樣圖森破! 機緣巧合,前段時間在焦點技術(shù)大會上聽到一位大牛關(guān)于Backbone的介紹,于是小僧最近一段時間研究了一下Backbone相關(guān)的內(nèi)容。 在《Developing Backbone Application》(戳這里查看此書電子版)這本書上,恰好有幾段關(guān)于MVC相關(guān)的內(nèi)容,看完這段內(nèi)容之后,小僧突然有醍醐灌頂之感。原來為什么MVC不是一種設(shè)計模式這個問題還真的是個問題,看起來是小僧自己執(zhí)念太重了! 罪過罪過。 彌陀佛~~! (淘寶的一位牛人白汀 @白汀UX 翻譯了《Developing Backbone Application》這本書,完整的在線電子版請戳這里,小僧友情建議一下這位大牛,請注意翻譯質(zhì)量,錯別字和語句不通順的問題太多了點?。?/p> 為了讓各位道友也能領(lǐng)悟到設(shè)計模式里面的一些奧妙,小僧特作此文。 稍安勿躁,讓小僧給各位濕主解說一番。 (這里就不對著原文翻譯了,為了方便各位道友理解,小僧總結(jié)一下其中的精髓,E文好的請點瀏覽器右上角。) MVC的起源1979年,Trygve Reenskaug 這位牛人在Smalltalk-80系統(tǒng)上首次提出了MVC的概念,最初的時候叫做Model-View-Controller-Editor。 (我擦,1979年小僧還在佛祖那兒念經(jīng)呢吧?) 1994年,Gof(Gang of Four)在《Design Patterns: Elements of Reusable Object-Oriented Software》一書中對MVC模式做了深入的解析。 Trygve Reenskaug最初提出MVC的目的是為了把數(shù)據(jù)(Model)和視圖(View)分離開來,然后用控制器(Controller)作膠水來粘合M和V之間的關(guān)系。 很顯然,這樣做的目的是為了實現(xiàn)注意點分離這樣一個更高層次的設(shè)計理念,也就是讓專業(yè)的對象做專業(yè)的事情,View就只負責視圖相關(guān)的東西,Model就只負責描述數(shù)據(jù)模型,Controller負責總控,各自協(xié)作,別總摻和到一起亂成一鍋粥! 最古典的MVC實現(xiàn)請注意上一小節(jié)中的兩個年份,1979年,計算機還不是屌絲能玩兒得起的東西!那時候比爾蓋茨還是個小學生,并且他還沒有輟學創(chuàng)辦MicroSoft,那時候人們不知道什么是Windows,當然,也沒有什么GUI的概念。 各位道友可以想想一下,黑黑的命令行,一串一串的文本字符... 嗯嗯,就是那個樣子的! 顯然,在這樣的歷史背景之下,原始的MVC模式顯然不是如今所理解的那種樣子。 在Smalltalk-80上的那個古典實現(xiàn)上,View和Controller都是要監(jiān)聽Model的,也就是說,只要數(shù)據(jù)發(fā)生變化,視圖和控制器都會收到通知的! 也就是這個樣子的: C和M,V和M之間都是通過Observer pattern (觀察者模式)來實現(xiàn)的。 對于這種古典的實現(xiàn)細節(jié),請參見Martin Fowler的這篇文章。 為什么GOF的23種設(shè)計模式里面沒有MVC?好了,到這里應(yīng)該來解釋為什么MVC不是一種設(shè)計模式這個問題了。 對于這個問題,直接引用@白汀UX 的譯文如下:
嗯嗯,知道為什么MVC沒有被GOF當作【一種】模式來對待了吧? 因為它實際上是三種模式的合體! (如果以后有人問你這個問題,你可以直接引述上面這段話,絕對高端大氣上檔次!一下就能把TA給震住?。?/p> 前端MVC與經(jīng)典MVC的差異正如前文所述,在當初提出MVC這種設(shè)計理念的歷史條件之下,基本上還沒有圖形界面,當然像JavaScript這種東西也是不存在的! 但是,如今不同了!在如今前端框架(尤其是各種JavaScript框架)大爆炸的背景下,幾乎所有的框架都會號稱自己具有MVC的特性。 但是,有一點請注意,如今的MVC實現(xiàn)與古典的MVC實現(xiàn)方式已經(jīng)大不相同了。 下面拿Backbone和Ext來舉兩個例子。 Backbone中的MVC實現(xiàn)方式對于最新版本的Backbone來說,它不再區(qū)分出獨立的Controller,它的控制器代碼與View是寫在一起的,僅僅明確區(qū)分出了Model的概念,舉個栗子: 呃,請不要在意那些細節(jié),看紅框的部分即可。 第一處,顯然Employee是一個Model; 第二處和第三處,顯然那EmployeeView是一個View; 第四處,setText這個方法顯然是充當Controller的角色。 很顯然,在Backbone的這種實現(xiàn)之下,View和Controller合體了,并沒有抽象出獨立的Controller這種東西。 顯然,這是古典MVC的一個變種,也就是原書作者所謂的MV*。 各位道友請仔細想想,Backbone的這種做法有沒有道理? Ext4.x中的MVC實現(xiàn)再來看Ext4.x中的MVC實現(xiàn)。 從以上示例項目截圖(controller/model/view等目錄)可以看出來(此圖來自Ext官方的說明文檔),Ext4.x采用了古典的MVC設(shè)計方案,它明確地抽象出了Controller這個類。 為什么小僧堅持認為Ext4里面的MVC是一種過度設(shè)計?熟悉Ext歷代版本的道友會知道,在Ext4.x之前,并沒有做出前面這樣的區(qū)分。 【以下純屬個人看法,僅供參考】 與Backbone相比,Ext4.x的這個設(shè)計純屬雞肋,實際上,對于帶有GUI界面的代碼來說,Controller是無法獨立于View而存在的。 因為,在Controller里面一定需要到處訪問View中的內(nèi)容,Controller是無法獨善其身的! Ext4.x的這個實現(xiàn)為了MVC而MVC的一個絕佳例子。 在Ext4.x中,類似為了模式而模式的例子不勝枚舉,據(jù)小僧不懷好意的推測,這一定是Jack離開之后這幫人亂搞的結(jié)果。 這也是為什么Ext4.x的運行效率如此之差的原因,之一。 小僧都替你們捉急有木有?!??! 對于4.x的效率問題,網(wǎng)上的吐槽不計其數(shù),各位道友可自行咨詢度娘。 為什么小僧認為MVP/MV*才是最佳設(shè)計理念這里請區(qū)分好概念,設(shè)計理念和具體實現(xiàn)方式不是一回事。 在關(guān)于Backbone的這本書中,作者還提出了MV*和MVP (Model-View-Presenter) 的說法,不得不說,這是非常具有洞察力的見解。 其中的Presenter可以用來與服務(wù)端交互,獲得Model數(shù)據(jù),以及把Model提交到服務(wù)端等等。 在當前MVC很多的實現(xiàn)里面,與服務(wù)端的交互是寫在Model里面的(Backbone和Ext都是這樣)。 小僧認為,這種實現(xiàn)方式有待商榷,如果在Model里面含有后臺交互的代碼,在不同的場景下顯然無法達到復用Model的目的。 比如,在場景一下面你希望數(shù)據(jù)模型訪問 myApp/delUser.action,而在場景二下面你希望它訪問 myApp/daddUser.action,這種情況你就麻煩了不是? 而且,與后臺的交互過程應(yīng)該抽象成獨立的數(shù)據(jù)傳輸層,在這一點上Ext的實現(xiàn)略好。 因此,MV*、MVVM、MVP都可以看作MVC的現(xiàn)代衍生版,M和V一定要明確區(qū)分,至于要不要抽象出其它類,其它類是應(yīng)該和M合體還是應(yīng)該和V合體,各位道友看著辦即可! 結(jié)語當初提出MVC,是為了實現(xiàn)關(guān)注點分離這樣一種設(shè)計理念,MVC只是實現(xiàn)這一理念的一種方式而已。因此,不必拘泥于一定要抽象出Model/View/Controller這樣的類結(jié)構(gòu)。 學習模式!運用模式!超越模式! 心中無碼,一切都無碼! 彌陀佛~~! |
|