閱讀目錄:html
一. MVC, MVP, MVVM誕生的需求?java
二. 一段典型的耦合代碼web
三. MVC模式後端
3.1 主動MVC服務器
3.2 被動MVC架構
3.3 Web應用中的MVC框架mvc
3.4 MVC總結app
MVC, MVP和MVVM都是用來解決界面呈現和邏輯代碼分離而出現的模式。之前只是對它們有部分的瞭解,沒有深刻的研究過,對於一些裏面的概念和區別也是隻知其一;不知其二。如今一邊查資料,並結合本身的理解,來談一下對於這三種模式思想的理解,以及它們的區別。歡迎各位高手拍磚。php
閱讀目錄:html
一. MVC, MVP, MVVM誕生的需求?java
二. 一段典型的耦合代碼web
三. MVC模式後端
3.1 主動MVC服務器
3.2 被動MVC架構
3.3 Web應用中的MVC框架mvc
3.4 MVC總結app
軟件中最核心的,最基本的東西是什麼? 是的,是數據。咱們寫的全部代碼,都是圍繞數據的。 圍繞着數據的產生、修改等變化,出現了業務邏輯。 圍繞着數據的顯示,出現了不一樣的界面技術。 框架
沒有很好設計的代碼,經常就會出現數據層(持久層)和業務邏輯層還有界面代碼耦合的狀況。
ORM等框架,解耦合了業務邏輯和數據之間的耦合,業務邏輯再也不關心底層數據如何存儲和讀取。全部數據呈現給業務邏輯層的就是一個個的對象。 而MVC, MVP, MMVM用來解決業務邏輯和視圖之間的耦合。
{
SqlDataAdapter adapter = new SqlDataAdapter("select * from Table1","server=.;database=db;uid=sa;pwd=password"); DataSet ds = new DataSet("ds1"); adapter.Fill(ds); this.GridView1.DataSource = ds; this.GridView1.DataBind(); }
上面的這段代碼中,既包含了數據訪問,還包含的頁面展現。當項目複雜程度更高,這種代碼就會變得很是難以維護,層次也不清晰。
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫。MVC開始是存在於桌面程序中的,M是指業務模型,V是指用戶界面,C則是控制器,使用MVC的目的是將M和V的實現代碼分離,從而使同一個程序可使用不一樣的表現形式
MVC的理論思想對應的是主動MVC, 這裏的主動的意思是, Model會主動通知View更新。而咱們使用MVC框架, Struts, asp.net mvc等都不是主動MVC(視圖的更新都是經過Controller完成的)
Model
用於封裝與應用程序的業務邏輯相關的數據以及對數據的處理方法。 模型中數據的變化通常會經過一種刷新機制被公佈。爲了實現這種機制,那些用於監視此模型的視圖必須事先在此模型上註冊,從而,視圖能夠了解在數據模型上發生的改變。
View
視圖層負責數據的展現。 在視圖中通常沒有程序上的邏輯。爲了實現視圖上的刷新功能,視圖須要訪問它監視的數據模型(Model),所以應該事先在被它監視的數據那裏訂閱Model的事件。
Controller
控制器是M和V之間的鏈接器,用於控制應用程序的流程。它處理事件並做出響應。「事件」包括用戶的行爲和數據模型上的改變。
下圖是被動MVC中的流程,和主動MVC不一樣之處是, View沒有訂閱Model數據變化的事件,等待Model來通知須要根據新的數據來更新View. 在被動MVC中,Controller負責通知View, 有數據變化,須要更新視圖。
被動MVC 中,與主動MVC的區別在於: 一、模型對視圖和控制器一無所知,它僅僅是被它們使用 二、控制器使用視圖,並通知它更新數據顯示 三、視圖僅僅是在控制器通知它去模型取數據的時候它才這麼作(視圖並不會訂閱或監視模型的更新)
Web中的MVC框架都是被動MVC模式,由於web應用中, 因爲http是基於請求和響應方式協同工做的,所以當服務器端的model(數據)發生變化時,它不會當即更新客戶端的view,只有客戶端從新請求或刷新頁面時才更新.
下圖是典型的MVC框架中的MVC一個請求流程。
MVC優勢
MVC使用的誤區
1.把Model理解成實體類(Entity),在MVC中Model應該包含2部分功能,一部分是處理業務邏輯,一部分是提供View顯示的數據 2.把業務邏輯所有放在Controller端
這兩個誤區本質上都是對Model的做用不明致使的。
Model在MVC架構中起的做用很是重要,它應該是業務邏輯真正的實現層。因此Model的其實是Business Model(業務模型)。而Controller僅僅起一個「橋樑」做用,它負責把View的請求轉發給Model,再負責把Model處理結束的消息通知View。Controller是用來解耦View和Model的,具體一點說,就是爲了讓UI與邏輯分離(界面與代碼分離)。
引自http://www.techopedia.com/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, 關聯StudentListView, StudentEditView. 對於StudentListView, Student Model提供Student的集合數據來顯示StudentListView 對於StudentEditView, Student Model提供單個Student數據來展現StudentEditView而且響應StudentEditView的保存操做。
可是這只是完美的狀況,實際應用中,在ListView上,不僅僅顯示Student的信息,可能還須要這個Student的歷史成績,家庭狀況, 老師信息。而這些是Student Model不能提供的。 也許咱們能夠擴展Student Model, 將Student Model可以提供的信息擴展,包含成績信息等,這自己也能夠。可是,若是Student顯示的View,這個須要只是須要額外的成績信息,另外一個View只是須要額外的家庭信息,Student Model是否是有些疲於奔命,你能知道還會有多少個差別化的View的需求? 並且讓邏輯端代碼這樣不斷的修改來適應View端,好嗎?
因爲MVC的設計思想是從Model出發,而沒有考慮到View端的複雜性,這樣致使的問題是Model難以符合複雜多變的View端變化。 相對這點,MVP和MVVM就要好得多。它們都獨立出了Presenter 和ViewModel來對應每一個View。
四. MVP模式
4.1 MVP的思想
4.2 UI界面接口化
4.3 Presenter —— Model和View之間的橋樑
4.4 MVP的代碼結構和時序圖
4.5 MVP模式總結
五. MVVM模式
5.1 MVVM模式的設計思想
5.2 MVVM模式結構圖
六. MVC, MVP和MVVM模式使用場景總結
MVP模式也是一種經典的界面模式。MVP中的M表明Model, V是View, P是Presenter。 下面例子中的完整代碼,能夠在這裏下載: WinformMVP源碼 你們還能夠比較園中Artech的這篇文章 談談關於MVP模式中V-P交互問題
MVP模式在我看來,是一個真正意義上的隔離View的細節和複雜性的模式。爲何這麼說: 由於在其它模式中V都表明的是UI界面, 是一個html頁面,XAML文件或者winform界面。可是在MVP模式中的V表明的是一個接口,一個將UI界面提煉而抽象出來的接口。接口意味着任何實現了該接口的界面,都可以複用已有的Presenter和Model代碼。
要很好的理解MVP, 就要有把UI界面接口化的能力。看下面的界面中,將紅色標記的User Control抽象一下,就能獲得下面的接口
public interface IUserAdd { event EventHandler UserAddEvent; string UserName { get; set; } string UserAge { get; set; } }
界面中的2個輸入框被抽象成了UserName和UserAge兩個屬性。Save按鈕的點擊事件,被抽象成了事件UserAddEvent。winform中實現該接口的代碼以下:
public partial class UserAdd : UserControl, IUserAdd { public event EventHandler UserAddEvent; public string UserName { set { this.txbName.Text = value; } get { return this.txbName.Text; } } public string UserAge { set { this.txbAge.Text = value; } get { return this.txbAge.Text; } } public UserAdd() { InitializeComponent(); } private void btnAdd_Click(object sender, EventArgs e) { if (UserAddEvent != null) UserAddEvent(this, e); } }
下面拿UserAge屬性來解釋一下,UI界面接口化的魔力。當後端代碼要獲取界面上的年齡值,就只須要get屬性, 要更新界面顯示的時候,就只須要set屬性。 這個時候,後端代碼對於界面的操做,被抽象成了對於UserAge屬性的操做了,也就是和具體的界面顯示無關了。
上文提到的後端代碼中,包含了P和M. M和MVC中同樣,指的是邏輯代碼。P則是Model和View之間的橋樑,負責將對應的Model和View組合到一塊兒。
針對上面的IUserAdd, 對應的Presenter代碼是:
public class UserAddPresenter:IPresenter { private readonly IUser _model; private readonly IUserAdd _view; private readonly ApplicationFacade _facade = ApplicationFacade.Instance; //這裏的facade是Presenter之間通訊用的,詳細能夠看完整代碼 //Presenter構造函數中,將view和model做爲參數傳入 public UserAddPresenter(IUser model, IUserAdd view) { _model = model; _view = view; WireUpViewEvents(); } private void WireUpViewEvents() { _view.UserAddEvent += _view_UserAdd; } //當view的UserAdd事件觸發,取得UI中的數據,調用model邏輯處理,添加新用戶。 //同時發送User_ADDED消息到系統中(系統中其它UI部分接收消息,好比這裏的DataGrid,它接收到User_ADDED以後,會刷新) private void _view_UserAdd(object sender, EventArgs e) { var user = new User { Name = _view.UserName, Age = Convert.ToInt32(_view.UserAge) }; _model.AddItem(user); _facade.SendNotification(ApplicationFacade.USER_ADDED); } }
這裏的MVP中的代碼結構圖和時序圖,可以更好的幫助理解MVP模式
在MVP裏,Presenter徹底把Model和View進行了分離,主要的程序邏輯在Presenter裏實現。並且,Presenter與具體的 View是沒有直接關聯的,而是經過定義好的接口進行交互,從而使得在變動View時候能夠保持Presenter的不變,即重用! 不只如此,咱們還能夠編寫測試用的View,模擬用戶的各類操做,從而實現對Presenter的測試 —— 而不須要使用自動化的測試工具。 咱們甚至能夠在Model和View都沒有完成時候,就能夠經過編寫Mock Object(即實現了Model和View的接口,但沒有具體的內容的)來測試Presenter的邏輯。
MVP的優點
一、模型與視圖徹底分離,咱們能夠修改視圖而不影響模型 二、能夠更高效地使用模型,由於全部的交互都發生在一個地方——Presenter內部 三、咱們能夠將一個Presener用於多個視圖,而不須要改變Presenter的邏輯。這個特性很是的有用,由於視圖的變化老是比模型的變化頻繁。 四、若是咱們把邏輯放在Presenter中,那麼咱們就能夠脫離用戶界面來測試這些邏輯(單元測試)
MVVM模式中,一個ViewModel和一個View匹配,它沒有MVP中的IView接口,而是徹底的和View綁定,全部View中的修改變化,都會自動更新到ViewModel中,同時ViewModel的任何變化也會自動同步到View上顯示。
這種自動同步之因此可以的緣由是ViewModel中的屬性都實現了observable這樣的接口,也就是說當使用屬性的set的方法,都會同時觸發屬性修改的事件,使綁定的UI自動刷新。(在WPF中,這個observable接口是 INotifyPropertyChanged; 在knockoutjs中,是經過函數ko.observable() 和ko.observrableCollection()來實現的)
因此MVVM比MVP更升級一步,在MVP中,V是接口IView, 解決對於界面UI的耦合; 而MVVM乾脆直接使用ViewModel和UI無縫結合, ViewModel直接就能表明UI. 可是MVVM作到這點是要依賴具體的平臺和技術實現的,好比WPF和knockoutjs, 這也就是爲何ViewModel不須要實現接口的緣由,由於對於具體平臺和技術的依賴,本質上使用MVVM模式就是不能替換UI的使用平臺的.
這裏是MVVM模式的結構圖,可以幫助更加容易的理解MVVM模式:
因爲在winform中沒法像WPF同樣,支持數據和界面的雙向綁定以及事件的監控,因此,在winform中MVP是最佳選擇。 WPF和html界面中使用Knockout,實現了observable, 因此使用MVVM.(應該說WPF就是爲使用MVVM設計的) 在web應用中,因爲http是基於請求和響應方式協同工做的, 沒法一直保持鏈接狀態,因此沒法達到MVP中Presenter之間的消息傳遞和MVVM中的ViewModel和界面之間的綁定, 因此MVC是最佳的選擇。
轉自:http://www.cnblogs.com/JustRun1983/p/3679827.html