MVP模式是类似于MVC模式的一种设计模式,最近在做项目学习过程中遇到,弄了很久终于有一些眉目,这是学习过程中的一些笔记。
MVP指的是实体对象Model、视图Viw和业务处理Presenter。MVP的作用是解耦UI渲染、业务逻辑和数据实体的关系。在普通的winform中,业务和界面是写在一起的,一般都是同一个Load或Click方法中,使View和Controller紧密联系。在MVP中,我们将界面渲染放在View里面,也就是winfrom的窗体应用类;将业务关系放在Presenter类中,这就是MVP中的业务数据类;最后的数据实体与数据库的交互放在Model中,是三者各司其职。
一般的MVP中,我们是在Presenter中主动使用View,也就是界面控件形态都是由Presenter去主动控制的。而建立这两者之间的联系,就是在Presenter中注册View的事件,当界面发生由用户触发事件时,这个事件会通过View传递到Presenter中,并在Presenter中调用Model的数据方法,最后Presenter调用在类中引用的View的实例去改变界面形态,下面是一些方法的实现,这里着重说明Presenter和View的关系。
首先,我们定义View的接口类IView,里面就一个数据实体的引用:

  1. public interface IView<T>:IView
  2. {
  3. T Model { get; set; }
  4. }

public interface IView:IView

接下来,定义View的下一级接口,这里是定义视图一些控件和事件:

  1. public interface IMainForm<T> : IView<T>
  2. {
  3. Button TestButton { get;} //定义MainFrom的按钮引用
  4. TextBox TestTextBox { get; } //定义MianForm的文本框引用
  5. event EventHandler ViewLoadEvent; //定义窗体加载完毕执行事件
  6. event EventHandler ButtonSubmitEvent; //定义按钮事件
  7. void ShowSubmitDialog(); //定义自定义的事件
  8. }

public interface IMainForm : IView

最后就是View的实现类,里面是实现的接口方法和属性,包含一个按钮及一个文本框,这里有一个继承了的MvpForm类和PresenterBinding的特性,一会再说:

  1. [PresenterBinding(typeof(MainFormPresenter))]
  2. public partial class MainForm : MvpForm , IMainForm<MainFormModel>
  3. {
  4. public MainForm()
  5. {
  6. InitializeComponent();
  7. }
  8.  
  9. public MainFormModel Model { get; set; }
  10. public TextBox TestTextBox { get { return txtText; } }
  11. public Button TestButton { get { return btnSubmit; } }
  12.  
  13. public event EventHandler ViewLoadEvent;
  14. public event EventHandler ButtonSubmitEvent;
  15.  
  16. private void MainForm_Load(object sender, EventArgs e)
  17. {
  18. if (ViewLoadEvent != null) ViewLoadEvent(sender, e);
  19. }
  20.  
  21. public void ShowSubmitDialog()
  22. {
  23. MessageBox.Show("to submit?");
  24. }
  25.  
  26. private void btnSubmit_Click(object sender, EventArgs e)
  27. {
  28. if (ButtonSubmitEvent != null) ButtonSubmitEvent(sender , e);
  29. }
  30. }

public partial class MainForm : MvpForm , IMainForm

定义完View的内容,就可以看一下Presenter,同样,先有接口,再有实现,先定义Presenter的接口:

  1. public interface IPresenter<T>:IPresenter where T : class, View.IView
  2. {
  3. T View { get; }
  4. }

public interface IPresenter:IPresenter where T : class, View.IView

这里再定义一个Presenter的抽象类,用于统一各个不同View对应的Presenter类,其定义如下:

  1. public abstract class Presenter<T> : IPresenter<T> where T : class, View.IView
  2. {
  3. private readonly T view;
  4.  
  5. //这里的view作为引用,用于在presenter中获取View的实例
  6. protected Presenter(T view)
  7. {
  8. this.view = view;
  9. }
  10.  
  11. public T View { get { return view; } }
  12. }

public abstract class Presenter : IPresenter where T : class, View.IView

最后就是对应的View的Presenter类了:

  1. class MainFormPresenter:Presenter<View.IMainForm<Model.MainFormModel>>
  2. {
  3. public MainFormPresenter(View.IMainForm<Model.MainFormModel> view)
  4. : base(view)
  5. {
  6. view.Model = new Model.MainFormModel();
  7.  
  8. view.ViewLoadEvent += On_ViewLoad;
  9. view.ButtonSubmitEvent += On_ButtonSubmitClick;
  10. init();
  11. }
  12.  
  13. public void init()
  14. {
  15. //To Do something...
  16. }
  17.  
  18. public void On_ViewLoad(object sender, EventArgs e)
  19. {
  20. //To Do something...
  21. }
  22.  
  23. public void On_ButtonSubmitClick(object sender, EventArgs e)
  24. {
  25. View.ShowSubmitDialog();//通过view的实例调用view的方法来改变控件形态
  26. }
  27. }

class MainFormPresenter:Presenter<View.IMainForm>

这里定义了Presenter和View的接口和实现,下面就是如何将这两个不同的模块联合在一起,这里,使用的是.net的特性和反射。
首先,先建立特性类PresenterBindingAttribute,通过在View的实现类标记该特性类和指定对应的Presenter类,就可以获取View和Presenter的对应关系了,该类同样要标注特性AttributeUsage和继承Attribute类,同时定义两个属性参数:

  1. [AttributeUsage(AttributeTargets.Class,AllowMultiple = true)]
  2. public sealed class PresenterBindingAttribute : Attribute
  3. {
  4. public Type PresenterType { get;private set; }
  5.  
  6. public Type ViewType { get; set; }
  7.  
  8. public PresenterBindingAttribute(Type presenterType)
  9. {
  10. PresenterType = presenterType;
  11. ViewType = null;
  12. }
  13. }

public sealed class PresenterBindingAttribute : Attribute

接下来,就是通过反射去建立view和presenter的关系,这里建立PerformBinding类:

  1. public IPresenter PerformBinding(IView viewInstance)
  2. {
  3. IPresenter presenter = null;
  4. Type t = viewInstance.GetType(); //获取该视图的类类型
  5. object[] attrs = t.GetCustomAttributes(typeof(PresenterBindingAttribute), false); //获取该类上的附加特性集合
  6. //遍历特性集合,找到Presenter类型附加的特性,通过该特性建立实例
  7. foreach (PresenterBindingAttribute pba in attrs)
  8. {
  9. Type newt = pba.PresenterType; //获取Presenter类类型
  10. //建立Presenter实例,这里的构造参数是View的对象,这样就使两者建立了联系
  11. Object obj = Activator.CreateInstance(pba.PresenterType, viewInstance);
  12. presenter = obj as IPresenter;
  13. }
  14. return presenter;
  15. }

public IPresenter PerformBinding(IView viewInstance)

那么,这个类PerformBinding在哪里使用,一般是在应用View启动是就要注册实例,这里为了解除类间的强耦合,就添加一个中间类。在前面的View的实现类中,是继承自一个MvpForm的类,这个MvpForm就使注册View和Presenter关系的类,接下来看MvpForm的实现:

  1. public partial class MvpForm : Form,IView
  2. {
  3. private readonly PresenterBinder presenterBinder = new PresenterBinder();
  4. public MvpForm()
  5. {
  6. presenterBinder.PerformBinding(this); //注册关系
  7. }
  8. }

public partial class MvpForm : Form,IView

这样,就建立了View与Presenter之间的关系,每次View页面启动,就先执行父类MvpForm的构造函数,注册View和Presenter的关系,相应的逻辑可以写在Presenter中,View的作用就是作为UI的渲染。以后添加View和Presenter实现类时,只需要继承和实现相应的类和接口,并在View实现类添加相应的对应类特性,就可实现MVP的设计关系。

c#中winform的MVP模式的简单实现的更多相关文章

  1. Android架构篇--MVP模式的介绍篇

    摘要: 在MVVM成熟之前MVP模式在Android上有被神化的趋势,笔者曾经在商业项目中从零开始大规模采用过MVP模式对项目进行开发.在使用MVP模式进行开发的时候发现项目的结构模式对开发是有一定的 ...

  2. MVP模式入门(结合Rxjava,Retrofit)

    本文MVP的sample实现效果: github地址:https://github.com/xurui1995/MvpSample 老规矩,在说对MVP模式的理解之前还是要再谈谈MVC模式,了解了MV ...

  3. 在Andoid开发中使用MVP模式来解耦,增加可测试性

    by Jeff Angelini posted on 7/20/2011 2:35:00 PM 将应用程序UI的表现从Ui的逻辑中分离是一个好的想法.这种分离减少了代码耦合,代码更加干净, 甚至可以有 ...

  4. Android -- 思考 -- 为什么要在项目中使用MVP模式

    1,其实有时候一直在找借口不去思考这个问题,总是以赶项目为由,没有很认真的思考这个问题,为什么我们要在项目中使用MVP模式,自己也用MVP也已经做了两个项目,而且在网上也看了不少的文章,但是感觉在高层 ...

  5. MVP模式在Android项目中的使用

    以前在写项目的时候,没有过多考虑架构模式的问题,因为之前一直做J2EE开发,而J2EE都是采用MVC模式进行开发的,所以在搭建公司项目的时候,也是使用类似MVC的架构(严格来讲,之前的项目还算不上MV ...

  6. 从最简单的HelloWorld理解MVP模式

    版权声明:本文为博主原创文章,转载请注明出处:http://www.cnblogs.com/joy99/p/6116855.html 大多数编程语言相关的学习书籍,都会以hello,world这个典型 ...

  7. Android 中的MVP 模式

    MVP模式的核心思想: MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成功接口,Model类还是原来的Model. MVC 其中View层其实就是程序的UI界面,用于向用户展示 ...

  8. MVP模式在Android开发中的应用

    一.MVP介绍      随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责.为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互.同一 ...

  9. 浅析前端开发中的 MVC/MVP/MVVM 模式

    MVC,MVP和MVVM都是常见的软件架构设计模式(Architectural Pattern),它通过分离关注点来改进代码的组织方式.不同于设计模式(Design Pattern),只是为了解决一类 ...

随机推荐

  1. channelartlist标签调用实例

    channelartlist标签,大家都知道在DedeCMS的系统中,我们可以用这个标签进行循环子栏目及其栏目的文档数据,这也是DedeCMS系统中,唯一一个支持标签嵌套的调用标签,以DedeV5.6 ...

  2. 反人类的MyEclipse之-eclipse设置花括号换行显示

    http://www.cnblogs.com/zhwl/archive/2012/12/17/2821806.html 习惯了C的代码风格,用Eclipse的风格,实在是看得卵子痛.尤其是大括号放在最 ...

  3. C Primer Plus(第五版)8

    第 8 章 字符输入/输出和输入确认 在本章中你将学习下列内容: · 有关输入,输出以及缓冲和非缓冲输入之间的区别的更多内容. · 从键盘模拟文件结尾条件的方法. · 如何重定向将你的程序与文件相连接 ...

  4. SpringMVC 注解事务

    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactio ...

  5. 【转】android的一些开源项目

    自己一直很喜欢Android开发,就如博客副标题一样,我想做个好的App. 在摸索过程中,GitHub上搜集了很多很棒的Android第三方库,推荐给在苦苦寻找的开发者,而且我会不定期的更新这篇文章. ...

  6. GoldenGate: Extract Abend with Detect Inconsistency in Pdata (文档 ID 1355067.1)

    APPLIES TO: Oracle GoldenGate - Version 10.4.0.0 and laterInformation in this document applies to an ...

  7. V$SGA_RESIZE_OPS.STATUS = ERROR, and MMAN / auto-tuning stops.

    Oracle Server - Standard Edition - Version: 10.2.0.3This problem can occur on any platform. SYMPTOMS ...

  8. ownDocument和documentElement

    <!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...

  9. 海外支付:抵御信用卡欺诈的CyberSource

    海外支付:抵御信用卡欺诈的CyberSource 吴剑 2014-06-04 原创文章,转载必需注明出处:http://www.cnblogs.com/wu-jian 吴剑 http://www.cn ...

  10. pytest学习笔记(三)

    接着上一篇的内容,这里主要讲下参数化,pytest很好的支持了测试函数中变量的参数化 一.pytest的参数化 1.通过命令行来实现参数化 文档中给了一个简单的例子, test_compute.py ...