MVP设计模式的实现

 

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#

====================================================多线程

MVP模式与MVC模式(转)架构

MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。做为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通讯是经过Presenter (MVC中的Controller)来进行的,全部的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是经过 Controller。Alex在他的blog中对于这二者之间的比较很直观也比较清楚,原文能够下面的地址找到: http://ameleta.spaces.live.com/blog/cns!5F6316345A821420!163.entry

【译文】: 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了,那么视图颇有可能也须要变动。

附:

http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/MVP.mspx?mfr=true

http://www.codeproject.com/useritems/ModelViewPresenter.asp

============================

 

winform MVP实现

 

之前写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://www.cnblogs.com/fer-team/ 业务网站:http://www.alichuntian.com 本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。
 
===============================================================

.NET程序员应该熟悉的开发模式

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。也就是这种架构:

image

而对于J2EE的开发者来讲熟悉的是下图。 

image

(说明:这两幅图copy自是daxnet文)

MVC是什么

MVC是一个很经典的结构,而且其又其思想衍生出不少变种好比MVP,MVVP。传统的MVC结构之一是这样的(拿主动型MVC来讲):

image

好比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同样好用。

image

在MVP模式中咱们须要本身定制各个View(web页面或者窗体)对应的IView和IPresenter、IModel。IView要对IPresenter暴露操做UI、数据绑定的接口,IPresenter对IView要暴露当UI事件触发须要调用的接口,IPresenter根据IView传递过来的请求调用业务接口并根据结果操做UI。举个简单的例子,一个计算“x+y=?”的程序。若是咱们这样定义IPresenter和IView

  1. public interface IPresenter   
  2.     {   
  3.         IView View { get; set; }   
  4.         void CalculateResult();   
  5.     }  
  6.  
  7. public interface IView   
  8.     {   
  9.         IPresenter Presenter { get; set; }   
  10.         void ShowResult(string result);   
  11.         int ValueOne { get; }   
  12.         int ValueTwo { get; }   
  13.     } 

IPresenter的实现以下(这里从简把IModel去掉了)

Presenter

  1. namespace ClientLibrary  
  2. {  
  3.     public class Presenter : IPresenter  
  4.     {  
  5.         private IView _view;  
  6.         public IView View  
  7.         {  
  8.             get 
  9.             {  
  10.                 return _view;  
  11.             }  
  12.             set 
  13.             {  
  14.                 _view = value;  
  15.                 _view.Presenter = this;  
  16.             }  
  17.         }  
  18.  
  19.         private static readonly string RESULT_FORMATTER = "{0}+{1},the result is {2}";  
  20.         public void CalculateResult()  
  21.         {  
  22.             if (_view != null)  
  23.             {  
  24. var result = string.Format(RESULT_FORMATTER, _view.ValueOne, _view.ValueTwo, _view.ValueOne + _view.ValueTwo);  
  25.                 _view.ShowResult(result);  
  26.                 this.A = 123;  
  27.             }  
  28.         }  
  29.         private int _a;  
  30.         public int A  
  31.         {  
  32.             set 
  33.             {  
  34.                 A = value;  
  35.             }  
  36.         }  
  37.     }  
View的实现以下(那silverlight为例,换成别的也行)

MainPage

  1. namespace debug  
  2. {  
  3.     public partial class MainPage : UserControl, IView  
  4.     {  
  5.         public MainPage()  
  6.         {  
  7.             InitializeComponent();  
  8.         }  
  9.  
  10.         private IPresenter _presenter;  
  11.  
  12. private void btn_Click(object sender, RoutedEventArgs e)  
  13.         {  
  14.             if (_presenter != null)  
  15.             {  
  16.                 _presenter.CalculateResult();  
  17.             }  
  18.             #region hidden  
  19.             /*int total = 0;  
  20.             try  
  21.             {  
  22. total = int.Parse(tb1.Text) + int.Parse(tb2.Text);  
  23. MessageBox.Show("计算结果:" + total.ToString());  
  24.             }  
  25.             catch (Exception ex)  
  26.             {  
  27.                 MessageBox.Show("出错啦" + ex.ToString());  
  28.             }  
  29.             finally  
  30.             {  
  31.                 tb1.Text = string.Empty;  
  32.                 tb2.Text = string.Empty;  
  33.             }*/ 
  34.             #endregion  
  35.  
  36.         }  
  37.  
  38.         public IPresenter Presenter  
  39.         {  
  40.             get 
  41.             {  
  42.                 return _presenter;  
  43.             }  
  44.             set 
  45.             {  
  46.                 _presenter = value;  
  47.             }  
  48.         }  
  49.  
  50.         public void ShowResult(string result)  
  51.         {  
  52.             MessageBox.Show(result);  
  53.         }  
  54.  
  55.         public int ValueOne  
  56.         {  
  57.             get { return int.Parse(tb1.Text); }  
  58.         }  
  59.  
  60.         public int ValueTwo  
  61.         {  
  62.             get { return int.Parse(tb2.Text); }  
  63.         }  
  64.     }  

一个很简单的东西,看上去写成的要多些那么一坨东西,可是好处是显而易见的,就是更换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

  1. public abstract class ViewModelBase : System.ComponentModel.INotifyPropertyChanged, IDisposable   
  2.     {   
  3.         public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;   
  4.         protected void OnPropertyChanged(string propertyName)   
  5.         {   
  6.             if (PropertyChanged != null)   
  7.             {   
  8.       var arg = new System.ComponentModel.PropertyChangedEventArgs(propertyName);   
  9.                 PropertyChanged(this, arg);   
  10.             }   
  11.         }   
  12.         public virtual void Dispose()   
  13.         {   
  14.              
  15.         }   
  16.     } 

 

  1. DemoViewModel public class DemoViewModel : ViewModelBase     
  2.  {          
  3. #region fields          
  4. private string _propertyA;          
  5. #endregion          
  6. #region presentation properties          
  7. public string PropertyA          
  8. {              
  9. get              
  10. {                 
  11.  return _propertyA;           
  12.    }              
  13. set        
  14.       {                  
  15. if (_propertyA != value)                
  16. {                      
  17. _propertyA = value;                   
  18. base.OnPropertyChanged("PropertyA");             
  19.      }         
  20.      }        }        
  21.   #endregion    } 

第二种是利用DependencyObject和DependencyProperty。

PeopleItemViewModel

  1. public class PeopleItemViewModel : DependencyObject, IPeopleItemViewModel  
  2.     {  
  3.         public PeopleItemViewModel()  
  4.         {  
  5.               
  6.         }  
  7. public static readonly DependencyProperty SimpleUserDataProperty = DependencyProperty.Register("SimpleUserData", typeof(SimpleUserData), typeof(PeopleItemViewModel));  
  8. public static readonly DependencyProperty RelativeSimpleUserDataProperty = DependencyProperty.Register("RelativeSimpleUserData", typeof(ObservableCollection<SimpleUserData>), typeof(PeopleItemViewModel));  
  9. public static readonly DependencyProperty AllSimpleUserDataProperty = DependencyProperty.Register("AllSimpleUserData", typeof(ObservableCollection<SimpleUserData>), typeof(PeopleItemViewModel));  
  10.  
  11.         public SimpleUserData SimpleUserData  
  12.         {  
  13.             get 
  14.             {  
  15.                 return (SimpleUserData)base.GetValue(SimpleUserDataProperty);  
  16.             }  
  17.             set 
  18.             {  
  19.                 if (!base.CheckAccess())  
  20.                 {  
  21.                     Dispatcher.Invoke(new Action(  
  22.                         () =>  
  23.                         {  
  24.                             SimpleUserData = value;  
  25.                         }));  
  26.                 }  
  27.                 else 
  28.                     base.SetValue(SimpleUserDataProperty, value);  
  29.             }  
  30.         }  
  31.         public ObservableCollection<SimpleUserData> RelativeSimpleUserData  
  32.         {  
  33.             get 
  34.             {  
  35. return (ObservableCollection<SimpleUserData>)base.GetValue(RelativeSimpleUserDataProperty);  
  36.             }  
  37.             set 
  38.             {  
  39.                 if (!base.CheckAccess())  
  40.                 {  
  41.                     Dispatcher.Invoke(new Action(  
  42.                         () =>  
  43.                         {  
  44.                             RelativeSimpleUserData = value;  
  45.                         }));  
  46.                 }  
  47.                 else 
  48.                 {  
  49. base.SetValue(RelativeSimpleUserDataProperty, value);  
  50. var collectionView = CollectionViewSource.GetDefaultView(value);  
  51. collectionView.SortDescriptions.Add(new SortDescription("Distance", ListSortDirection.Ascending));  
  52.                 }  
  53.             }  
  54.         }  
  55.         public ObservableCollection<SimpleUserData> AllSimpleUserData  
  56.         {  
  57.             get 
  58.             {  
  59.       return (ObservableCollection<SimpleUserData>)base.GetValue(AllSimpleUserDataProperty);  
  60.             }  
  61.             set 
  62.             {  
  63.                 if (!base.CheckAccess())  
  64.                 {  
  65.                     Dispatcher.Invoke(new Action(  
  66.                         () =>  
  67.                         {  
  68.                             AllSimpleUserData = value;  
  69.                         }));  
  70.                 }  
  71.                 else 
  72.                 {  
  73. base.SetValue(AllSimpleUserDataProperty, value);  
  74. var collectionView = CollectionViewSource.GetDefaultView(value);  
  75. collectionView.SortDescriptions.Add(new SortDescription("Distance", ListSortDirection.Ascending));  
  76.                 }  
  77.             }  
  78.         }  

在View中绑定ViewModel。

为了方便,咱们能够在app.xaml中将须要的viewmode放到全局资源字典中。

image

而后再咱们的vs视图设计器Properties(中文版显示的是“属性”)页上选择为绑定源设置绑定目标(包括source和path等)以及必要的值转换器等等便可。

image image image

(PS:虽然vs很强大,但我的仍是建议熟悉xaml的绑定语法,想当初用vs2008搞wpf的时候貌似尚未这么方便的设计器。。。)

原文连接:http://www.cnblogs.com/wJiang/archive/2010/12/11/1903039.html

相关文章
相关标签/搜索