深刻理解MVC

MVC無人不知,可不少程序員對MVC的概念的理解彷佛有誤,換言之他們一直在錯用MVC,儘管即便如此軟件也能被寫出來,然而軟件內部代碼的組織方式倒是不科學的,這會影響到軟件的可維護性、可移植性,代碼的可重用性。html

 

MVC即Model、View、Controller即模型、視圖、控制器。我在和同行討論技術,閱讀別人的代碼時發現,不少程序員傾向於將軟件的業務邏輯放在Controller裏,將數據庫訪問操做的代碼放在Model裏。程序員

 

最終軟件(網站)的代碼結構是,View層是界面,Controller層是業務邏輯,Model層是數據庫訪問。數據庫

 

不知道你們知不知道另一種軟件開發模式三層架構,它和MVC類似之處是也分爲三層,分別是UI層表示用戶界面,BLL層表示業務邏輯,DAL層表示數據訪問。三層架構曾經紅極一時,MVC大行其道以後它就銷聲匿跡了, 可如今看來, 它彷佛只是改頭換面, 裝扮成MVC的樣子,而且深受程序員們的歡迎,由於它的這種分層方式和前文描述的MVC一模一樣。編程

 

再說的直白點,不少程序員將MVC當成了三層架構在用,這看起來彷佛沒什麼問題,畢竟三層架構也是一種和MVC齊名的架構模式。可問題在於用三成架構的思路寫MVC,那麼寫出來的東西既不是三成架構也不是MVC,到是像一個什麼都不是四不像。熟悉天龍八部的同窗應該知道這樣一段情節,吐蕃番僧鳩摩智強行用道家的小無相功爲基礎修煉少林的七十二絕技和易筋經最終致使走火入魔。其實用這個例子來形容如今一些程序員用三層架構的思想寫MVC最恰當不過了,三層架構的核心思想是面向接口編程和各層之間的解耦和可替換性,MVC框架中沒有這種概念,由於MVC要面對的問題本就不是三成架構要面對的問題,因此以MVC爲基礎寫出來的三成架構是不會具有三層架構的核心要義的,換言之,這種代碼是放棄了三層架構和MVC的精華,得到了它們的糟粕,是愚蠢的編碼方式。設計模式

 

我吐槽了這麼多, 對於吐槽的理由要是說不出個因此然來,估計要被人噴死,下面就來講說MVC本質原理和正確使用方式,固然,這裏的MVC指的最純粹MVC,適合各種軟件,而不只僅指Web框架中的變體MVC,然而萬變不離其宗,文中所述的MVC思想一樣適用於Web開發。瀏覽器

 

MVC要實現的目標是將軟件用戶界面和業務邏輯分離以使代碼可擴展性、可複用性、可維護性、靈活性增強。服務器

 

View層是界面,Model層是業務邏輯,Controller層用來調度View層和Model層,將用戶界面和業務邏輯合理的組織在一塊兒,起粘合劑的效果。因此Controller中的內容能少則少,這樣才能提供最大的靈活性。架構

 

比方說,有一個View會提交數據給Model進行處理以實現具體的行爲,View一般不會直接提交數據給Model,它會先把數據提交給Controller,而後Controller再將數據轉發給Model。假如此時程序業務邏輯的處理方式有變化,那麼只須要在Controller中將原來的Model換成新實現的Model就能夠了,控制器的做用就是這麼簡單, 用來將不一樣的View和不一樣的Model組織在一塊兒,順便替雙方傳遞消息,僅此而已。框架

 

合理的使用MVC有不少好處,要一一道滿是一件異常困難的任務。在這裏咱們經過一個反面示例來側面的證實正確使用MVC的好處與依據。學習

 

如前文所言, 不少程序員偏心於將業務邏輯放在Controller中,我極力反對這種作法,如今我就來證實這中作法的錯誤性。

 

咱們知道在寫程序時,業務邏輯的重複使用是常常要面對的場景。 若是業務邏輯寫在控制器中, 要重用它的惟一方法就是將它提高到父類之中,經過繼承來達到代碼複用的效果。但這麼作會帶來一個巨大的反作用,違背了一項重要的面向對象設計原則:接口隔離。

 

什麼是接口隔離,我在這裏簡單的講述一下。通俗一點講,接口隔離就是當一個類須要繼承另外一個類時, 若是被繼承的類中有繼承的類用不到的方法或者屬性時,就不要去實現這個繼承。若是真的情非得已必需要繼承,那麼也須要從被繼承的類中再提取出一個只包含須要部分功能的新類型,最終去繼承這個新類型纔是正確的作法。 換句話說,實現繼承的時候,不要去繼承那些用不到的事物。

 

回到以前的話題,經過繼承父控制器的方式複用業務邏輯時,每每會出現爲了重用一個方法而繼承來一大堆用不到的方法,表面上看起來彷佛沒什麼問題,可是這會使代碼變的難以理解,
久而久之, 軟件的代碼會朝着不健康的方向發展。

 

要知道,使用繼承的條件是很苛刻的,咱們學習面向對象變編程繼承特性時,第一課就是隻有知足IS-A(是一個)關係時纔可使用繼承,若是僅僅是複用代碼,並非咱們使用繼承的理由。使用組合是複用代碼提倡的方式,也就是所謂的HAS-A(有一個)的關係,相信每一個程序員都聽過「少用繼承,多有組合」這句話,這句話是軟件開發業的先驅們千錘百煉總結出來的,值得咱們去遵循。

 

各Model之間是能夠相互調用的, Controller也能夠無障礙的調用Model,所以將業務邏輯放在Model中能夠靈活的使用組合的方式複用代碼。

 

而Controller之間是不能夠相互調用的,要複用代碼只能將代碼提高至父類,經過繼承實現,顯然這種作法既不正確,也不靈活,所以徹底不提倡。

 

綜上所述,僅僅只是代碼複用這一點,也足以將「厚Controller,薄Model」這種不健康的MVC思想打入十八層地獄。

 

如今咱們大概知道了代碼應該如何分佈於MVC三層之間, 知其然,而且也知其因此然。接下來咱們再從另外一個角度深入剖析MVC,脫它個精光,讓它赤條條展現在咱們眼前。

 

衆所周知,GoF總結過23個設計模式,這23個設計模式是某些特定的編程問題的特效藥,這是業內公認的。

 

MVC是一種模式,但卻在GoF總結出來的這個23個設計模式以外,確切的說它不是一種設計模式,它是多種設計模式的組合,並不只僅只是一個單獨的一個模式。

 

組成MVC的三個模式分別是組合模式、策咯模式、觀察者模式,MVC在軟件開發中發揮的威力,最終離不開這三個模式的默契配合。 那些崇尚設計模式無用論的程序員,請了解只要大家使用MVC,就離不開設計模式。

 

注意,如下內容以這三個設計模式的知識爲基礎,若是對這三個設計模式沒概念,或許會閱讀困難。

 

先說組合模式在MVC中扮演什麼樣的角色。

 

組合模式只在視圖層活動, 視圖層的實現用的就是組合模式,固然,這裏指的實現是底層的實現,是由編程框架廠商作的事情,用不着普通程序員插手。

 

組合模式的類層次結構是樹狀的, 而咱們作Web時視圖層是html頁面,html的結構不正是樹狀的嗎,這其實就是一個組合模式的應用,只是瀏覽器廠商已經把界面相關的工做幫咱們作掉了,但它確確實實是咱們應用MVC的其中一部分,只是咱們感受不到罷了,這也是咱們以爲View是實現起來最簡單最沒有歧義的一層的緣由。

 

除網頁之外的其餘用戶界面程序,如WPF、Android、Asp.net等等都是使用樹狀結構來組織界面控件對象的,由於組合模式就是從界面設計的通用解決方案總提煉出來的。因此與其說MVC選擇了組合模式,還不如說組合模式是一定會存在MVC中的,由於只要涉及到用戶界面,組合模式就一定存。事實上即便不理解組合模式,也不影響程序員正確的使用MVC,組合模式本就存在於程序員接觸不到的位置。

 

然而,觀察者模式和策略模式就顯得比較重要,是實實在在MVC中接觸的到的部分。

 

觀察者模式有兩部分組成,被觀察的對象和觀察者,觀察者也被稱爲監聽者。對應到MVC中,Model是被觀察的對象,View是觀察者,Model層一旦發生變化,View層即被通知更新。View層和Model層互相之間是持有引用的。 咱們在開發Web MVC程序時,由於視圖層的html和Model層的業務邏輯之間隔了一個http,因此不能顯示的進行關聯,可是他們觀察者和收聽者的關係卻沒有改變。當View經過http提交數據給服務器,服務器上的Model接受到數據執行某些操做,再經過http響應將結果回送給View,View(瀏覽器)接受到數據更新界面,這不正是一個接受到通知並執行更新的行爲嗎,是觀察者模式的另外一種表現形式。

 

可是,脫離Web,當經過代碼去純粹的表示一個MVC結構的時候,View和Model間無疑是觀察者和被觀察的關係,是以觀察者模式爲理論基礎的。即便在Web中由於http壁壘的緣由致使真正的實現有點走樣,可是原理核心和思路哲學倒是不變的。

 

最後是策略模式。策略模式是View和Controller之間的關係,Controller是View的一個策略,Controller對於View是可替換的, View和Controller的關係是一對多,在實際的開發場景中,也常常會碰到一個View被多個Controller引用,這即便策咯模式的一種體現,只是不那麼直觀而已。

 

總結一下,關於MVC各層之間關係所對應的設計模式

 

View層,單獨實現了組合模式

Model層和View層,實現了觀察者模式

View層和Controller層,實現了策咯模式

 

MVC就是將這三個設計模式在一塊兒用了,將這三個設計模式弄明白,MVC將毫無神祕感可言。若是不瞭解這三個設計模式去學習MVC,那無論怎麼學總歸是隻知其一;不知其二,用的時候也不免不會出想問題。

 

再次回到最前面討論的業務邏輯應該放在Controller仍是Model的問題上,從設計模式的角度講,策略模式中的策略一般都很小很薄,不會包含太多的內容, Controller是一個策略, 天然不該該在裏面放置過多的內容,不然要替換一個新的會至關麻煩,與此同時也會破壞View-Model的觀察者模式,彷彿View-Controller之間即實現了策略模式又實現了觀察者模式,這種混亂是罪惡的根源,是製造焦油坑讓程序員陷入其中沒法自拔的罪魁禍首。切忌,應當避免。

 

注:此文核心思想來自《head first設計模式》

相關文章
相關標籤/搜索