MVP模式及实例
最近在关注MVP模式的文章,看了张子阳的 MVP 模式实例解析和李春雷的MVP模式最佳实践(1)—MVP模式简介 ,自己也想弄一个来试试。
关于MVP模式的概念,网上很多,在此摘抄一段吧。
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
准确的说,MVP模式和三层架构相比,MVP模式的编码量比较大,我个人认为普通的项目如果不涉及到WinFrom 与WebFrom 之间的转换,最好不要用MVP的模式。
下面我就以我所理解的MVP模式写一个小实例,是关于某个员工基本信息的数据绑定与编辑的操作。
在员工基本信息的编辑界面中,需要展示的信息包括员工的工号,姓名,性别,籍贯,出生年月等等,在此实例中我只展示这五个字段,一个绑定员工信息的方法,以及一个更新员工信息的事件。
首先,定义员工的Model层,该层代码与三层架构的实体层是相同的。
1
namespace Model2
{3
using System;4
public class StaffInfo5
{6
private string _stfId;7
private string _stfName;8
private string _sex;9
private string _native;10
private string _birthDay;11

12
public StaffInfo()13
{14
}15

16
public StaffInfo(string stfId, string stfName, string sex, string native, string birthDay)17
{18
this._stfId = stfId;19
this._stfName = stfName;20
this._sex = sex;21
this._native = native;22
this._birthDay = birthDay;23
}24
/// <summary>25
/// 员工工号26
/// </summary>27
public string StfId28
{29
get { return _stfId; }30
set { _stfId = value; }31
}32
/// <summary>33
/// 员工姓名34
/// </summary>35
public string StfName36
{37
get { return _stfName; }38
set { _stfName = value; }39
}40
/// <summary>41
/// 性别42
/// </summary>43
public string Sex44
{45
get { return _sex; }46
set { _sex = value; }47
}48
/// <summary>49
/// 籍贯50
/// </summary>51
public string Native52
{53
get { return _native; }54
set { _native = value; }55
}56
/// <summary>57
/// 出生年月58
/// </summary>59
public string BirthDay60
{61
get { return _birthDay; }62
set { _birthDay = value; }63
}64
}65
}
第二步,定义员工的页面接口 IStaffDetailView ,在页面中,一般有一些常用的自定义函数,这时我们可以把它定义在父接口,然后用一个页面父类去实现它,如下面的MessageBox这个函数,就可以用这样的方式。那么我们页面接口就可以继承这个父接口,这样可以增强代码的重用性。
1
namespace Presenter2
{3
using System;4
using Model;5
public interface IStaffDetailView6
{7
/// <summary>8
/// 员工工号9
/// </summary>10
string StfId { get;}11

12
/// <summary>13
/// 员工姓名14
/// </summary>15
string StfName { get;}16

17
/// <summary>18
/// 性别19
/// </summary>20
string Sex { get;}21

22
/// <summary>23
/// 籍贯24
/// </summary>25
string Native { get;}26

27
/// <summary>28
/// 出生年月29
/// </summary>30
string BirthDay { get;}31

32
/// <summary>33
/// 绑定员工信息34
/// </summary>35
/// <param name="infos"></param>36
void BindDetail(StaffInfo> infos);37

38
/// <summary>39
/// 更新员工信息事件40
/// </summary>41
event EventHandler<EventArgs> UpdateEvent;42
}43
}
第三步,定义员工数据访问类,我这里只是给一个示例,真实的项目中当然要封装一下才行。
第四步,定义员工Presenter层
1
public class StaffDetailPresenter2
{3
private IStaffDetailView _view;4

5
public StaffDetailPresenter(IStaffDetailView view)6
{7
this._view = view;8
}9

10
/// <summary>11
/// 初始化页面12
/// </summary>13
/// <param name="IsPostBack">首次提交,WebFrom中,此值为IsPostBack,WinFrom中,此值为false</param>14
public void InitializeView(bool IsPostBack)15
{16
if(!IsPostBack)17
BindDetail();18
this._view.UpdateEvent += new EventHandler<EventArgs>(View_UpdateEvent);19
}20

21
private void BindDetail()22
{23
this._view.BindDetail(new Staff(this._view.StfId));24
}25

26
private void View_UpdateEvent(object sender, EventArgs e)27
{28
if (new Staff().UpdateStaff(new Staff(this._view.StfId, this._view.StfName, this._view.Sex, this._view.Native, this._view.BirthDay)))29
{30
this.BindDetail();31
this._view.MessageBox("更新成功");32
}33
else34
this._view.MessageBox("更新失败!");35
}36
}第五步:实现View接口,我这里以WebFrom为例,在页面中做了数据绑定与更新数据事件两个操作,还有如绑定GridView等等操作,大家可以探讨。
1
namespace Web2
{3
using System;4
using System.Data;5
using System.Data.SqlClient;6
using System.Configuration;7
using System.Collections;8
using System.Collections.Generic;9
using System.Web;10
using System.Web.Security;11
using System.Web.UI;12
using System.Web.UI.WebControls;13
using System.Web.UI.WebControls.WebParts;14
using System.Web.UI.HtmlControls;15
using Presenter;16
using Model;17

18
public partial class StaffDetail : Page, IStaffDetailView19
{20
#region 实现接口21
/// <summary>22
/// 员工工号23
/// </summary>24
public string StfId { get { if (object.Equals(Request.QueryString["stfId"], null)) return null; return Request.QueryString["stfId"].ToString(); } }25

26
/// <summary>27
/// 员工姓名28
/// </summary>29
public string StfName { get { return txtStfName.Text; } }30

31
/// <summary>32
/// 性别33
/// </summary>34
public string Sex { get { return ddlSex.SelectValue; } }35

36
/// <summary>37
/// 籍贯38
/// </summary>39
public string Native { get { return txtNative.Text; } }40

41
/// <summary>42
/// 出生年月43
/// </summary>44
public string BirthDay { get { return txtBirthDay.Text; } }45

46
/// <summary>47
/// 绑定员工信息48
/// </summary>49
/// <param name="info"></param>50
public void BindDetail(StaffInfo info)51
{52
lbStfId.Text = info.StfId;53
txtStfName.Text = info.StfName;54
ddlSex.SelectValue = info.Sex;55
txtNative.Text = info.Native;56
txtBirthDay.Text = info.BirthDay;57
}58

59
/// <summary>60
/// 弹出对话框61
/// </summary>62
/// <param name="msg">对话框消息</param>63
public void MessageBox(string msg)64
{65
string script = string.Format("<script language='javascript' type='text/javascript' defer>window.alert('{0}');</script>", msg);66
this.ClientScript.RegisterStartupScript(this.GetType(), "系统提示", script);67
}68

69
/// <summary>70
/// 更新员工信息事件71
/// </summary>72
public event EventHandler<EventArgs> UpdateEvent;73
#endregion74

75
protected void Page_Load(object sender, EventArgs e)76
{77
StaffDetailPresenter p = new StaffDetailPresenter(this);78
p.InitializeView(IsPostBack);79
}80

81
protected void btn_Update(object sender, EventArgs e)82
{83
if (this.UpdateEvent != null)84
this.UpdateEvent(sender, e);85
}86
}87
88
}以上是整个实例的代码。这个实例与李春雷的实例的大体结构类似,不同之处在于以下两点
1、视图接口中增加了按钮事件,这个思路来源于http://www.cnblogs.com/chinasf/archive/2006/12/20/597987.html;
2、明确了Model层与Control层的职责,在Model层的设计中我采用了与三层框架的实体层相同的方式,DataAccess作为Control层,它的作用在于对数据库进行操作。
欢迎大家来批评指正。
转自:http://www.cnblogs.com/easyit/archive/2009/05/12/1454786.html



浙公网安备 33010602011771号