MVC, MVP和MVVM都是用來解決界面呈現(xiàn)和邏輯代碼分離而出現(xiàn)的模式。以前只是對它們有部分的了解,沒有深入的研究過,對于一些里面的概念和區(qū)別也是一知半解?,F(xiàn)在一邊查資料,并結(jié)合自己的理解,來談一下對于這三種模式思想的理解,以及它們的區(qū)別。 一,MVC, MVP, MVVM誕生的需求? 軟件中最核心的,最基本的東西是什么? 是的,是數(shù)據(jù)。我們寫的所有代碼,都是圍繞數(shù)據(jù)的。 圍繞著數(shù)據(jù)的產(chǎn)生、修改等變化,出現(xiàn)了業(yè)務邏輯。 圍繞著數(shù)據(jù)的顯示,出現(xiàn)了不同的界面技術。 沒有很好設計的代碼,常常就會出現(xiàn)數(shù)據(jù)層(持久層)和業(yè)務邏輯層還有界面代碼耦合的情況。 ORM等框架,解耦合了業(yè)務邏輯和數(shù)據(jù)之間的耦合,業(yè)務邏輯不再關心底層數(shù)據(jù)如何存儲和讀取。所有數(shù)據(jù)呈現(xiàn)給業(yè)務邏輯層的就是一個個的對象。 而MVC, MVP, MMVM用來解決業(yè)務邏輯和視圖之間的耦合。 二,一段典型的耦合代碼
上面的這段代碼中,既包含了數(shù)據(jù)訪問,還包含的頁面展示。當項目復雜程度更高,這種代碼就會變得非常難以維護,層次也不清晰。 三,MVC模式 MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫。MVC開始是存在于桌面程序中的,M是指業(yè)務模型,V是指用戶界面,C則是控制器,使用MVC的目的是將M和V的實現(xiàn)代碼分離,從而使同一個程序可以使用不同的表現(xiàn)形式 3.1 主動MVC MVC的理論思想對應的是主動MVC, 這里的主動的意思是, Model會主動通知View更新。而我們使用MVC框架, Struts, asp.net mvc等都不是主動MVC(視圖的更新都是通過Controller完成的) Model 用于封裝與應用程序的業(yè)務邏輯相關的數(shù)據(jù)以及對數(shù)據(jù)的處理方法。 模型中數(shù)據(jù)的變化一般會通過一種刷新機制被公布。為了實現(xiàn)這種機制,那些用于監(jiān)視此模型的視圖必須事先在此模型上注冊,從而,視圖可以了解在數(shù)據(jù)模型上發(fā)生的改變。 View 視圖層負責數(shù)據(jù)的展示。 在視圖中一般沒有程序上的邏輯。為了實現(xiàn)視圖上的刷新功能,視圖需要訪問它監(jiān)視的數(shù)據(jù)模型(Model),因此應該事先在被它監(jiān)視的數(shù)據(jù)那里訂閱Model的事件。 Controller 控制器是M和V之間的連接器,用于控制應用程序的流程。它處理事件并作出響應?!笆录卑ㄓ脩舻男袨楹蛿?shù)據(jù)模型上的改變。 3.2 被動MVC 下圖是被動MVC中的流程,和主動MVC不同之處是, View沒有訂閱Model數(shù)據(jù)變化的事件,等待Model來通知需要根據(jù)新的數(shù)據(jù)來更新View. 在被動MVC中,Controller負責通知View, 有數(shù)據(jù)變化,需要更新視圖。 被動MVC 中,與主動MVC的區(qū)別在于: 1、模型對視圖和控制器一無所知,它僅僅是被它們使用 2、控制器使用視圖,并通知它更新數(shù)據(jù)顯示 3、視圖僅僅是在控制器通知它去模型取數(shù)據(jù)的時候它才這么做(視圖并不會訂閱或監(jiān)視模型的更新) 3.3. Web應用中的MVC框架 Web中的MVC框架都是被動MVC模式,因為web應用中, 由于http是基于請求和響應方式協(xié)同工作的,因此當服務器端的model發(fā)生變化時,它不會立即更新客戶端的view,只有客戶端重新請求或刷新頁面時才更新. 下圖是典型的MVC框架中的MVC一個請求流程。 3.4 MVC總結(jié) MVC優(yōu)點
MVC使用的誤區(qū) 1.把Model理解成實體類(Entity),在MVC中Model應該包含2部分功能,一部分是處理業(yè)務邏輯,一部分是提供View顯示的數(shù)據(jù) 2.把業(yè)務邏輯全部放在Controller端這兩個誤區(qū)本質(zhì)上都是對Model的作用不明導致的。Model在MVC架構(gòu)中起的作用非常重要,它應該是業(yè)務邏輯真正的實現(xiàn)層。所以Model的實際上是Business Model(業(yè)務模型)。而Controller僅僅起一個“橋梁”作用,它負責把View的請求轉(zhuǎn)發(fā)給Model,再負責把Model處理結(jié)束的消息通知View。Controller是用來解耦View和Model的,具體一點說,就是為了讓UI與邏輯分離(界面與代碼分離)。 引自http://www./definition/27454/model-mvc-aspnet Techopedia explains Model (MVC) The Model is the part of MVC which implements the domain logic. In simple terms, this logic is used to handle the data passed between the database and the user interface (UI). The Model is known as domain object or domain entity. The domain objects are stored under the Models folder in ASP.NET. The domain model represents the application perspective for the data to be handled whereas a view model is required to produce the engine that generates the View. This definition was written in the context of ASP.NET. MVC的缺點 完美的MVC應用場景應該是這樣的: 有個Student Model, 關聯(lián)StudentListView, StudentEditView. 對于StudentListView, Student Model提供Student的集合數(shù)據(jù)來顯示StudentListView 對于StudentEditView, Student Model提供單個Student數(shù)據(jù)來展示StudentEditView并且響應StudentEditView的保存操作。 但是這只是完美的情況,實際應用中,在ListView上,不單單顯示Student的信息,可能還需要這個Student的歷史成績,家庭情況, 老師信息。而這些是Student Model不能提供的。 也許我們可以擴展Student Model, 將Student Model能夠提供的信息擴展,包含成績信息等,這本身也可以。但是,如果Student顯示的View,這個需要只是需要額外的成績信息,另一個View只是需要額外的家庭信息,Student Model是不是有些疲于奔命,你能知道還會有多少個差異化的View的需求? 而且讓邏輯端代碼這樣不斷的修改來適應View端,好嗎? 由于MVC的設計思想是從Model出發(fā),而沒有考慮到View端的復雜性,這樣導致的問題是Model難以符合復雜多變的View端變化。 相對這點,MVP和MVVM就要好得多。它們都獨立出了Presenter 和ViewModel來對應每個View。 四、MVP模式 MVP模式也是一種經(jīng)典的界面模式。MVP中的M代表Model, V是View, P是Presenter。 下面例子中的完整代碼: WinformMVP源碼(http://files.cnblogs.com/JustRun1983/WinFormMVP.zip) 大家還可以比較園中Artech的這篇文章 談談關于MVP模式中V-P交互問題(http://www.cnblogs.com/artech/archive/2010/03/25/1696205.html) 4.1 MVP的思想 MVP模式在我看來,是一個真正意義上的隔離View的細節(jié)和復雜性的模式。為什么這么說: 因為在其它模式中V都代表的是UI界面, 是一個html頁面,XAML文件或者winform界面。但是在MVP模式中的V代表的是一個接口,一個將UI界面提煉而抽象出來的接口。接口意味著任何實現(xiàn)了該接口的界面,都能夠復用已有的Presenter和Model代碼。 4.2 UI界面接口化 要很好的理解MVP, 就要有把UI界面接口化的能力??聪旅娴慕缑嬷?,將紅色標記的User Control抽象一下,就能得到下面的接口
界面中的2個輸入框被抽象成了UserName和UserAge兩個屬性。Save按鈕的點擊事件,被抽象成了事件UserAddEvent。winform中實現(xiàn)該接口的代碼如下:
下面拿UserAge屬性來解釋一下,UI界面接口化的魔力。當后端代碼要獲取界面上的年齡值,就只需要get屬性, 要更新界面顯示的時候,就只需要set屬性。 這個時候,后端代碼對于界面的操作,被抽象成了對于UserAge屬性的操作了,也就是和具體的界面顯示無關了。 4.3 Presenter —— Model和View之間的橋梁 上文提到的后端代碼中,包含了P和M. M和MVC中一樣,指的是邏輯代碼。P則是Model和View之間的橋梁,負責將對應的Model和View組合到一起。 針對上面的IUserAdd, 對應的Presenter代碼是:
4.4 MVP的代碼結(jié)構(gòu)和時序圖 這里的MVP中的代碼結(jié)構(gòu)圖和時序圖,能夠更好的幫助理解MVP模式 4.5 MVP模式總結(jié) 在MVP里,Presenter完全把Model和View進行了分離,主要的程序邏輯在Presenter里實現(xiàn)。 而且,Presenter與具體的 View是沒有直接關聯(lián)的,而是通過定義好的接口進行交互,從而使得在變更View時候可以保持Presenter的不變,即重用! 不僅如此,我們還可以編寫測試用的View,模擬用戶的各種操作,從而實現(xiàn)對Presenter的測試 —— 而不需要使用自動化的測試工具。 我們甚至可以在Model和View都沒有完成時候,就可以通過編寫Mock Object(即實現(xiàn)了Model和View的接口,但沒有具體的內(nèi)容的)來測試Presenter的邏輯。 MVP的優(yōu)勢 1、模型與視圖完全分離,我們可以修改視圖而不影響模型 2、可以更高效地使用模型,因為所有的交互都發(fā)生在一個地方——Presenter內(nèi)部 3、我們可以將一個Presener用于多個視圖,而不需要改變Presenter的邏輯。這個特性非常的有用,因為視圖的變化總是比模型的變化頻繁。 4、如果我們把邏輯放在Presenter中,那么我們就可以脫離用戶界面來測試這些邏輯(單元測試) 五, MVVM模式 5.1 MVVM模式的設計思想 MVVM模式中,一個ViewModel和一個View匹配,它沒有MVP中的IView接口,而是完全的和View綁定,所有View中的修改變化,都會自動更新到ViewModel中,同時ViewModel的任何變化也會自動同步到View上顯示。 這種自動同步之所以能夠的原因是ViewModel中的屬性都實現(xiàn)了observable這樣的接口,也就是說當使用屬性的set的方法,都會同時觸發(fā)屬性修改的事件,使綁定的UI自動刷新。 (在WPF中,這個observable接口是 INotifyPropertyChanged; 在knockoutjs中,是通過函數(shù)ko.observable 和ko.observrableCollection來實現(xiàn)的) 所以MVVM比MVP更升級一步,在MVP中,V是接口IView, 解決對于界面UI的耦合; 而MVVM干脆直接使用ViewModel和UI無縫結(jié)合, ViewModel直接就能代表UI. 但是MVVM做到這點是要依賴具體的平臺和技術實現(xiàn)的,比如WPF和knockoutjs, 這也就是為什么ViewModel不需要實現(xiàn)接口的原因,因為對于具體平臺和技術的依賴,本質(zhì)上使用MVVM模式就是不能替換UI的使用平臺的. 5.2 MVVM模式結(jié)構(gòu)圖 這里是MVVM模式的結(jié)構(gòu)圖,能夠幫助更加容易的理解MVVM模式: 六, MVC, MVP和MVVM模式使用場景總結(jié) 由于在winform中無法像WPF一樣,支持數(shù)據(jù)和界面的雙向綁定以及事件的監(jiān)控,所以,在winform中MVP是最佳選擇。 WPF和html界面中使用Knockout,實現(xiàn)了observable, 所以使用MVVM.(應該說WPF就是為使用MVVM設計的) 在web應用中,由于http是基于請求和響應方式協(xié)同工作的, 無法一直保持連接狀態(tài),所以無法達到MVP中Presenter之間的消息傳遞和MVVM中的ViewModel和界面之間的綁定, 所以MVC是最佳的選擇。 不是在文章評論里回復 |
|