1. 程式人生 > >為什麼MVC不是一種設計模式? ---比較Backbone和Ext4.x在MVC實現上的差異

為什麼MVC不是一種設計模式? ---比較Backbone和Ext4.x在MVC實現上的差異

為什麼MVC不是一種設計模式?

---比較Backbone和Ext4.x在MVC實現上的差異

轉載:http://damoqiongqiu.iteye.com/blog/1949256

大漠窮秋

前言

聖人云:不想做媽咪的小姐不是好碼農。

每一個碼農的心中都有一個終極理想,那就是有一天不用再Coding。

在成為媽咪的道路上,“設計模式”被認為是一項必備的技能。

因此,經常有溼主會問小僧這樣一個問題:為什麼MVC不是一種設計模式呢?

對於這樣naive的問題,小僧向來是嗤之以鼻的,你們啊!圖樣圖森破!

機緣巧合,前段時間在焦點技術大會上聽到一位大牛關於Backbone的介紹,於是小僧最近一段時間研究了一下Backbone相關的內容。

在《Developing Backbone Application》(戳這裡檢視此書電子版)這本書上,恰好有幾段關於MVC相關的內容,看完這段內容之後,小僧突然有醍醐灌頂之感。原來為什麼MVC不是一種設計模式這個問題還真的是個問題,看起來是小僧自己執念太重了!

罪過罪過。

彌陀佛~~!

(淘寶的一位牛人白汀 @白汀UX 翻譯了《Developing Backbone Application》這本書,完整的線上電子版請戳這裡,小僧友情建議一下這位大牛,請注意翻譯質量,錯別字和語句不通順的問題太多了點!)

為了讓各位道友也能領悟到設計模式裡面的一些奧妙,小僧特作此文。

稍安勿躁,讓小僧給各位溼主解說一番。

(這裡就不對著原文翻譯了,為了方便各位道友理解,小僧總結一下其中的精髓,E文好的請點瀏覽器右上角。)

MVC的起源

1979年,Trygve Reenskaug 這位牛人在Smalltalk-80系統上首次提出了MVC的概念,最初的時候叫做Model-View-Controller-Editor。

(我擦,1979年小僧還在佛祖那兒唸經呢吧?)

Trygve Reenskaug最初提出MVC的目的是為了把資料(Model)檢視(View)分離開來,然後用控制器(Controller)作膠水來粘合M和V之間的關係。

很顯然,這樣做的目的是為了實現注意點分離這樣一個更高層次的設計理念,也就是讓專業的物件做專業的事情,View就只負責檢視相關的東西,Model就只負責描述資料模型,Controller負責總控,各自協作,別總摻和到一起亂成一鍋粥!

最古典的MVC實現

請注意上一小節中的兩個年份,1979年,計算機還不是屌絲能玩兒得起的東西!那時候比爾蓋茨還是個小學生,並且他還沒有輟學創辦MicroSoft,那時候人們不知道什麼是Windows,當然,也沒有什麼GUI的概念。

各位道友可以想想一下,黑黑的命令列,一串一串的文字字元...

嗯嗯,就是那個樣子的!

顯然,在這樣的歷史背景之下,原始的MVC模式顯然不是如今所理解的那種樣子。

在Smalltalk-80上的那個古典實現上,View和Controller都是要監聽Model的,也就是說,只要資料發生變化,檢視和控制器都會收到通知的!

也就是這個樣子的:



 

C和M,V和M之間都是通過Observer pattern (觀察者模式)來實現的。

對於這種古典的實現細節,請參見Martin Fowler的這篇文章

為什麼GOF的23種設計模式裡面沒有MVC?

好了,到這裡應該來解釋為什麼MVC不是一種設計模式這個問題了。

對於這個問題,直接引用@白汀UX 的譯文如下:

GoF (Gang of Four,四人組, 《Design Patterns: Elements of Reusable Object-Oriented Software》/《設計模式》一書的作者:Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides)並沒有把MVC提及為一種設計模式,而是把它當做“一組用於構建使用者介面的類集合”。在他們看來,它其實是其它三個經典的設計模式的演變:觀察者模式(Observer)(Pub/Sub), 策略模式(Strategy)和組合模式(Composite)。根據MVC在框架中的實現不同可能還會用到工廠模式(Factory)和裝飾器(Decorator)模式。我在另一本免費的書“JavaScript Design Patterns For Beginners”中講述了這些模式,如果你有興趣可以閱讀更多資訊。

正如我們所討論的,models表示應用的資料,而views處理螢幕上展現給使用者的內容。為此,MVC在核心通訊上基於推送/訂閱模型(驚訝的是 在很多關於MVC的文章中並沒有提及到)。當一個model變化時它對應用其它模組發出更新通知(“publishes”),訂閱者 (subscriber)——通常是一個Controller,然後更新對應的view。觀察者——這種自然的觀察關係促進了多個view關聯到同一個 model。

對於感興趣的開發人員想更多的瞭解解耦性的MVC(根據不同的實現),這種模式的目標之一就是在一個主題和它的觀察者之間建立一對多的關係。當這個 主題改變的時候,它的觀察者也會得到更新。Views和controllers的關係稍微有點不同。Controllers幫助views對不同使用者的輸 入做不同的響應,是一個非常好的策略模式列子。

嗯嗯,知道為什麼MVC沒有被GOF當作【一種】模式來對待了吧?

因為它實際上是三種模式的合體

(如果以後有人問你這個問題,你可以直接引述上面這段話,絕對高階大氣上檔次!一下就能把TA給震住!)

前端MVC與經典MVC的差異

正如前文所述,在當初提出MVC這種設計理念的歷史條件之下,基本上還沒有圖形介面,當然像JavaScript這種東西也是不存在的!

但是,如今不同了!在如今前端框架(尤其是各種JavaScript框架)大爆炸的背景下,幾乎所有的框架都會號稱自己具有MVC的特性。

但是,有一點請注意,如今的MVC實現與古典的MVC實現方式已經大不相同了。

下面拿Backbone和Ext來舉兩個例子。

Backbone中的MVC實現方式

對於最新版本的Backbone來說,它不再區分出獨立的Controller,它的控制器程式碼與View是寫在一起的,僅僅明確區分出了Model的概念,舉個栗子:




 
 

呃,請不要在意那些細節,看紅框的部分即可。

第一處,顯然Employee是一個Model;

第二處和第三處,顯然那EmployeeView是一個View;

第四處,setText這個方法顯然是充當Controller的角色。

很顯然,在Backbone的這種實現之下,View和Controller合體了,並沒有抽象出獨立的Controller這種東西。

顯然,這是古典MVC的一個變種,也就是原書作者所謂的MV*。

各位道友請仔細想想,Backbone的這種做法有沒有道理?

Ext4.x中的MVC實現

再來看Ext4.x中的MVC實現。 




 
 

從以上示例專案截圖(controller/model/view等目錄)可以看出來(此圖來自Ext官方的說明文件),Ext4.x採用了古典的MVC設計方案,它明確地抽象出了Controller這個類

為什麼小僧堅持認為Ext4裡面的MVC是一種過度設計?

熟悉Ext歷代版本的道友會知道,在Ext4.x之前,並沒有做出前面這樣的區分。

【以下純屬個人看法,僅供參考】

與Backbone相比,Ext4.x的這個設計純屬雞肋,實際上,對於帶有GUI介面的程式碼來說,Controller是無法獨立於View而存在的。

因為,在Controller裡面一定需要到處訪問View中的內容,Controller是無法獨善其身的!

Ext4.x的這個實現為了MVC而MVC的一個絕佳例子。

在Ext4.x中,類似為了模式而模式的例子不勝列舉,據小僧不懷好意的推測,這一定是Jack離開之後這幫人亂搞的結果。

這也是為什麼Ext4.x的執行效率如此之差的原因,之一。

小僧都替你們捉急有木有?!!!

對於4.x的效率問題,網上的吐槽不計其數,各位道友可自行諮詢度娘。

為什麼小僧認為MVP/MV*才是最佳設計理念

這裡請區分好概念,設計理念具體實現方式不是一回事。

在關於Backbone的這本書中,作者還提出了MV*和MVP (Model-View-Presenter) 的說法,不得不說,這是非常具有洞察力的見解。

其中的Presenter可以用來與服務端互動,獲得Model資料,以及把Model提交到服務端等等。

在當前MVC很多的實現裡面,與服務端的互動是寫在Model裡面的(Backbone和Ext都是這樣)。




 
 

小僧認為,這種實現方式有待商榷,如果在Model裡面含有後臺互動的程式碼,在不同的場景下顯然無法達到複用Model的目的。

比如,在場景一下面你希望資料模型訪問 myApp/delUser.action,而在場景二下面你希望它訪問 myApp/daddUser.action,這種情況你就麻煩了不是?

而且,與後臺的互動過程應該抽象成獨立的資料傳輸層,在這一點上Ext的實現略好。

因此,MV*、MVVM、MVP都可以看作MVC的現代衍生版,M和V一定要明確區分,至於要不要抽象出其它類,其它類是應該和M合體還是應該和V合體,各位道友看著辦即可!

結語

當初提出MVC,是為了實現關注點分離這樣一種設計理念,MVC只是實現這一理念的一種方式而已。因此,不必拘泥於一定要抽象出Model/View/Controller這樣的類結構。

學習模式!運用模式!超越模式!

心中無碼,一切都無碼!

彌陀佛~~!

(請理性吐槽,否則回頭小僧到佛祖那兒說你壞話,哼!)