MVP:界面與業務邏輯分離在Winform中的應用html
MVP,Model-View-Presenter的縮寫。android
在MSDN上,下載了一個示例,http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/MVP.mspx?mfr=true程序員
採用的實現結構web
在Blog http://www.agilelabs.cn/blogs/wind_tower/archive/2006/01/26/626.aspx上,看到的實現結構ajax
在C# 開發環境中,爲了提升界面的開發效率,可採用數據綁定的形式。這樣,View中須要提供數據源,採用MSDN上定義的結構,實現起來更加方便一些。數據庫
同時,爲了提升對客戶請求的響應,採用多線程。因爲View中的數據綁定與Presenter中多線程的業務邏輯,須要同時訪問View中的數據源,這樣,對於一些特定的多線程處理需求,還須要Presenter提供刷新View的Public函數,並不能徹底實現:Presenter業務邏輯更新後,View能夠自動刷新c#
====================================================多線程
【譯文】: Model View Presenter vs Model View Controllermvc
簡介
在我工做中常常須要處理一些因爲開發人員沒能很清楚地理解MVC和MVP模式的區別的狀況下使用它們而產生的問題。在這篇文章中我將會闡述一下我對二者之間區別的一些理解。 在N層體系結構中MVC/P模式僅僅只是用於表示層(presentation layer),理解這一點很重要。這兩個模式並非關於怎麼構建數據層(data layer)和服務層(service layer)的,而是關於怎麼將數據(data)從用戶接口(view)中分離出來,以及用戶接口如何與數據進行交互的。這些模式的使用讓解除你的程序中表示層對對數據和控制邏輯的依賴,從而能夠自由的變動表示層。
這兩種模式的通常性概念
一、模型(Model)表示數據模型和業務邏輯(business logic)。模型並不老是DataSet,DataTable之類的東西,它表明着一類組件(components)或類(class),這些組件或類能夠向外部提供數據,同時也能從外部獲取數據並將這些數據存儲在某個地方。簡單的理解,能夠把模型想象成「外觀類(facade class)」。譯註:這裏的外觀是指「外觀模式」中所說的外觀。外觀的通常做用是爲一個複雜的子系統提供高層次的簡單易用的訪問接口,能夠參看下面的圖來理解它的原理:
二、視圖(View)將數據層現給用戶。通常的視圖都只是包含用戶界面(UI),而不包含界面邏輯。好比,Asp.net中包含控件的頁面(page)就是一個視圖。視圖能夠從模型中讀取數據,可是不能修改或更新模型。 三、層現器(Presenter)/控制器(Controller)包含了根據用戶在視圖中的行爲去更新模型的邏輯。視圖僅僅只是將用戶的行爲告知控制器,而控制器負責從視圖中取得數據而後發送給模型。
MVC/P模式的核心是爲了將模型從視圖/控制器中分離出來,從而使得模型獨立於它們,所以模型不包含對視圖和控制的引用。 什麼是MVC(Model View Presenter)模式?
一、爲了使得視圖接口能夠與模型和控制器進行交互,控制器執行一些初始化事件 二、用戶經過視圖(用戶接口)執行一些操做 三、控制器處理用戶行爲(能夠用觀察着模式實現)並通知模型進行更新 四、模型引起一些事件,以便將改變發告知視圖 五、視圖處理模型變動的事件,而後顯示新的模型數據 六、用戶接口等待用戶的進一步操做
這一模式的有一下幾個要點: 一、視圖並不使用控制器去更新模型。控制器負責處理從視圖發送過來的用戶操做並經過與模型的交互進行數據的更新 二、控制器能夠和視圖融合在一塊。Visual Studion中對Windows Forms的默認處理方式就是這樣的。【譯註:好比咱們雙擊一個Button,而後在它的事件裏寫處理邏輯,而後將處理的數據寫回模型中。這裏處理邏輯時間應該是控制器的功能,可是咱們並無專門寫一個控制器來作這件事情而是接受了VS的默認處理方式,將它寫在Form的代碼中,而這裏的Form在MVC中它就是一個View。因此這說vs默認的處理方式是將把控制器和視圖融合在一塊兒的。】 三、控制器不包含對視圖的渲染邏輯(rendering logic)
「主動—MVC」模式,也是一般意義下的MVC模式
【譯註:爲何說是主動的?View不是等Controller通知它Model更新了而後才從Model取數據並更新顯示,而是本身監視Model的更新(若是用觀察者模式)或主動詢問Model是否更新。前面那種等待Controller通知的方式是下面所介紹的「被動—MVC」的實現方式。】
「被動—MVC」模式 與主動MVC的區別在於: 一、模型對視圖和控制器一無所知,它僅僅是被它們使用 二、控制器使用視圖,並通知它更新數據顯示 三、視圖僅僅是在控制器通知它去模型取數據的時候它才這麼作(視圖並不會訂閱或監視模型的更新) 四、控制器負責處理模型數據的變化 五、控制器能夠包含對視圖的渲染邏輯
MVP模式
與「被動—MVC模式」很接近,區別在於「視圖並不使用模型」。在MVP模式中視圖和模型是徹底分離的,他們經過Presenter進行交互。 Presenter與控制器很是類似,可是它們也有一些的區別: 一、Presenter處理視圖發送過來的用戶操做(在MVC中視圖本身處理了這些操做) 二、它用更新過的數據去更新模型(在被動MVC中控制器只是通知視圖去更新過的模型中去取新的數據,而主動MVC中模型通知視圖去更新顯示,控制器不須要作工做) 三、檢查模型的更新(與被動MVC同樣) 四、(與MVC的主要區別)從模型中取數據而後將它們發送到視圖中 五、(與MVC的主要區別)將所作的更新告知視圖 六、(與MVC的區別)用Presenter渲染視圖
MVP的優點
一、模型與視圖徹底分離,咱們能夠修改視圖而不影響模型 二、能夠更高效地使用模型,由於因此的交互都發生在一個地方——Presenter內部 三、咱們能夠將一個Presener用於多個視圖,而不須要改變Presenter的邏輯。這個特性很是的有用,由於視圖的變化老是比模型的變化頻繁。 四、若是咱們把邏輯放在Presenter中,那麼咱們就能夠脫離用戶接口來測試這些邏輯(單元測試)。
MVP的問題
因爲對視圖的渲染放在了Presenter中,因此視圖和Persenter的交互會過於頻繁。
還有一點你須要明白,若是Presenter過多地渲染了視圖,每每會使得它與特定的視圖的聯繫過於緊密。一旦視圖須要變動,那麼Presenter也須要變動了。好比說,本來用來呈現Html的Presenter如今也須要用於呈現Pdf了,那麼視圖頗有可能也須要變動。
附:
============================
之前寫winform項目都是界面與實現邏輯都放在一塊兒,自從學了mvc3以後,又看了wpf的mvvp後,以爲winform的程序能夠這樣來寫。
首先定義視圖接口:
public interface IView<T> where T:class { T Model { get; set; } void BindingData(T model); }
而後定義Presenter接口:
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> public interface IPresention<T> where T : class { void InsertData(T model); void UpdateData(T model); void DeleteData(T model); }
實現IPresention<T>接口的類:
public class DataDictPresentation : IPresention<ResourceDict> { IView<ResourceDict> _view; IView<IList<ResourceDict>> _viewList; public DataDictPresentation(IView<ResourceDict> view) { _view = view; if (_view.Model != null) { _view.BindingData(_view.Model); } } public DataDictPresentation(IView<IList<ResourceDict>> view) { _viewList = view; PageIndex = 1; PageSize = 14; } public int PageIndex { get; set; } public int PageCount { get; set; } public int PageSize { get; set; } public void InsertData(ResourceDict model) { } public void UpdateData(ResourceDict model) { } public void Query(ResourceDict filter) { } public void DeleteData(ResourceDict model) { } }
最後在窗體頁面上實現:
public partial class DataDictBox : Form, IView<ResourceDict> { private DataDictPresentation presentation; public DataDictBox() { InitializeComponent(); Initialize(); } private static DataDictBox _instance; public static DataDictBox Instance { get { if (_instance == null || _instance.IsDisposed) { _instance = new DataDictBox(); } return _instance; } } private void Initialize() { this.Load += delegate { presentation = new DataDictPresentation(this); }; } public ResourceDict Model { get; set; } public void BindingData(ResourceDict item) { } public void SetData(ResourceDict item) { }
這樣完成了一個初步的MVP結構的模型。
http://developer.51cto.com/art/201012/238088.htm
咱們總會有這樣一個經驗:一個系統最不容易也最不該該變化的部分是領域邏輯,最容易變化也最應該變化的是數據的呈現方式。
在Java的各類應用中能夠說是處處可見MVC,J2EE貫穿MVC的概念,android的開發方式也是類MVC的,MVC結構對於作過Java應用的人而言簡直就是司空見慣。而在.NET這邊,因爲以前微軟爲你們提供的各類winform、ASP.NET項目典範(好比那個petshop series)將「三層」概念很好的灌輸到了.NET程序員的大腦中,許多.NET開發者凡是作個東西都要搬出本身最拿手的IModel、IDAL這樣的神器。
其實MVC與所謂的「三層架構」是兩個層次上的東西,前者是一種結構模式,然後者則是分層的角度去說。
一件很奇怪的事情,許多人知道「三層」殊不知道MVC,其實這要歸結與.NET的早期開發技術ASP.NET和winform這些page controller的典範讓許多人對三層誇誇其談卻對MVC視而不見甚至一無所知。什麼是page controller模式呢?搞.NET的大多都用過winform和webform,這種xxxform用起來很直觀,咱們想要作一個程序,ok,最簡單的方式就是拖拖拽拽幾個控件,而後在一個叫code behind的東西里寫這些UI事件的處理邏輯,加一大堆變量用於記錄數據和狀態,這樣一個程序就能出爐。這種開發方式對於一些小軟件系統的開發其實效率仍是蠻高的,後來人們看到其弊端---一旦修改UI,事件處理就要跟着變,可是業務仍是那個業務,憑什麼要修改非UI的代碼?因而有人提出「三層」,最樸素的理解就是將本來那堆事件處理裏的code分紅業務代碼和數據庫訪問代碼並轉移到其它類中,作多了就把那坨UI叫作UI,那坨業務代碼叫作BLL,那坨DAO叫作DAL。也就是這種架構:
而對於J2EE的開發者來講熟悉的是下圖。
(說明:這兩幅圖copy自是daxnet文)
MVC是什麼
MVC是一個很經典的結構,而且其又其思想衍生出不少變種好比MVP,MVVP。傳統的MVC結構之一是這樣的(拿主動型MVC來講):
好比web開發(好比ASP.NET MVC或者是Java的web開發方式),view就是純web頁面或者webservice,當提交一個表單/調用webservice或者ajax後會將數據提交給controller(固然期間可能會通過各類filterchain、listener這樣的東西)controller調用相應的業務模塊來處理這個請求,最終結果會更新View的顯示。
MVP
對於非自然MVC的框架
對於ASP.NET/winform而言,雖然能夠經過改造讓其支持MVC結構的開發(好比經過定製IHttpModule、IHttpHandler云云),可是在企業看來這些都算是邪門武功(由於這樣會喪失xxxform在開發上的不少特性好比快速開發)。大多數使用的是mvp模式。什麼是mvp呢?其實mvp是MVC的一個變種。由於用winform或者webform的話form始終是個阻礙MVC開發的問題。那麼好,咱們仍然使用designer和codebehind,其實一個架構設計的好壞是取決於人而不是具體的技術的,只要咱們OO一時強page controller同樣好用。
在MVP模式中咱們須要本身定製各個View(web頁面或者窗體)對應的IView和IPresenter、IModel。IView要對IPresenter暴露操做UI、數據綁定的接口,IPresenter對IView要暴露當UI事件觸發須要調用的接口,IPresenter根據IView傳遞過來的請求調用業務接口並根據結果操做UI。舉個簡單的例子,一個計算「x+y=?」的程序。若是咱們這樣定義IPresenter和IView
IPresenter的實現以下(這裏從簡把IModel去掉了)
Presenter
MainPage
一個很簡單的東西,看上去寫成的要多些那麼一坨東西,可是好處是顯而易見的,就是更換view很是方便,根本不用去改你的IPresenter、Presenter和業務。一切都是接口調用而不依賴具體實現,這就是好處。
你必需要懂的MVVM
對於.NET平臺的開發人員,託微軟的福分咱們擁有一種更爲強大的模型---MVVM。這應該算是作WPF/Silverlight應用的人必懂的一種結構,WPF/silverlight天生支持數據綁定和命令綁定(不過sl在命令綁定上還比較弱),這就爲咱們使用MVVM創造了可能。
View是什麼呢,純的View只有xaml或者附帶必要的只與View自己相關邏輯代碼。ViewModel,你能夠把它理解爲View具體呈現內容所依賴數據的一個抽象,在MVVM中View與ViewModel總會有一種綁定關係,一旦ViewModel中被綁定的數據發生改變View上的數據就會跟着變,相反也有可能,好比你的帳號密碼框內容發生變化,關聯的ViewModel中的數據就會被框架自動通知到。
在wpf/silverlight中,綁定是經過xaml語法來完成(雖然你能夠選擇用c#來寫但不符合mvvm的宗旨),而且綁定雙方的通知機制是有框架來完成,也就是說一個會xaml和blend的美工只需事先和coder商量下「我們的xx和xx是在哪一個ViewModel上叫XXX的屬性的XXX屬性……」問題以後就能夠各幹各的了。那麼ViewModel怎麼寫,咋view中又怎麼綁定到viewmodel呢?首先咱們談ViewModel。
說道ViewModel你須要知道依賴屬性和依賴對象的概念,這是wpf/silverlight的基礎因此很少說。有兩種方式寫ViewModel。第一種是本身去實現INotifyPropertyChanged接口,並在屬性變化時去調用NotifyPropertyChanged事件。
爲了方便咱們定義一個ViewModelBase的抽象基類,而後讓其餘ViewModel繼承這個基類。
ViewModelBase
第二種是利用DependencyObject和DependencyProperty。
PeopleItemViewModel
在View中綁定ViewModel。
爲了方便,咱們能夠在app.xaml中將須要的viewmode放到全局資源字典中。
而後再咱們的vs視圖設計器Properties(中文版顯示的是「屬性」)頁上選擇爲綁定源設置綁定目標(包括source和path等)以及必要的值轉換器等等便可。
(PS:雖然vs很強大,但我的仍是建議熟悉xaml的綁定語法,想當初用vs2008搞wpf的時候貌似尚未這麼方便的設計器。。。)
原文連接:http://www.cnblogs.com/wJiang/archive/2010/12/11/1903039.html