深入理解MVC模式

MVC模式結構圖
MVC即Model,View,Controller如上結構圖,分別對應模型,視圖,控制器。就目前而言,我們大多數人更傾向於將軟件的業務邏輯放在Controller裏,將數據庫訪問操作的代碼放入Model中,最終軟件的代碼結構是:View層是界面,Controller是業務邏輯,Model層神數據庫訪問。
說直白點,大多數人將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思想忘卻。

衆所周知,GoF總結過23設計模式,這23種設計模式是某些特地的編程問題的特效藥,這是業內公認的。
MVC是一種模式,但卻在GoF總結出來這23種設計模式之外,準確的說他不是一種設計模式,他是多種設計模式的組合,並不僅僅神一個單獨的模式。

組成MVC的三個模式分別是組合模式,策略模式,觀察者模式,MVC在軟件開發中發揮的威力,最終離不開這三個模式的默契配合。

一下內容以這三個設計模式的知識爲基礎,如果對着三個設計模式沒概念,或許閱讀困難。

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

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

組合模式的類層次結構是樹狀的, 而我們做Web時視圖層是html頁面,html的結構不正是樹狀的嗎,這其實就是一個組合模式的應用,只是瀏覽器廠商已經把界面相關的工作幫我們做掉了,但它確確實實是我們應用MVC的其中一部分,只是我們感覺不到罷了,這也是我們覺得View是實現起來最簡單最沒有歧義的一層的原因。
除網頁以外的其他用戶界面程序,如WPF、Android、http://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之間即實現了策略模式又實現了觀察者模式,這種混亂是罪惡的根源,是製造焦油坑讓程序員陷入其中無法自拔的罪魁禍首。切忌,應當避免。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章