1.MVP框架介紹:
最近公司內部培訓,正好理一下項目的架構,目前最主要的產品還是用的MVP軟件設計模式,就順便查查資料來做個總結。
1.1什么是MVP?
MVP是Model-View—Presenter的縮寫,從網上找到的資料來看,大多數時候,對於MVP的介紹還是基於MVC,關注點基本上就集中在Presenter上面了,wiki上有個簡單的說明(
MVP模式),先從定義來大概理解下這個模式:

1.2MVP各自的使用規則和相互的交互
這三個模塊,一般情況下,對於view的理解是沒什么爭議的,就是界面展示;關於Model和Presenter的功能,還是有些爭議,簡單的來說,一個是業務邏輯,一個是界面控制邏輯,但是實際定義的時候可能就沒那么清楚了,關於這兩個模塊定位的區分,我看到了一篇比較有用的文章,雖然是MVC的,但是原理是差不多的(
點這里查看原文):
實體對象(entity object): 通常是來自域模型中的對象(也就是現實世界),它常對應於數據庫表和文件,這些數據表 和文件中存儲了執行用例所需的數據。有些實體對象是“臨時”對象(如搜索結果),當用例 結束后將消失。 邊界對象(boundary object): 參與者使用它來同系統交互,這通常包含窗口,屏幕,對話框和菜單。如果有GUI原型, 將會知道許多主要的邊界對象是什么。 控制對象(control object): 將邊界對象和實體對象關聯起來(通常被稱為控制器,因為它們通常不是真正的對象), 它包含了大部分應用邏輯,它們在用戶和存儲的數據之間架起一座橋梁。控制對象中包含經常 修改的業務規則和策略。這樣修改只需要在這些對象中進行,而不會涉及到用戶界面和數據庫 模式。控制器偶爾 (20%的時間內)也會是設計中的“真正對象”,但大部分時間內,控制器只 是一個占位符,用於避免您遺漏用例要求的任何功能和系統行為。
關於這三個模塊的交互,可以用一張圖來體現:
Presenter做為Model和View的中間層,維護頁面操作狀態,從Model獲取數據,百度百科里用的圖Presenter和model之間是雙向綁定的,有點沒看懂,原則上,Model是不會處理Presenter的。
1.3關於MVP的一些概念上的問題
我之前對於Model的理解是有些誤差的,不管是MVC還是MVP,我之前以為Model是數據模型,只是數據庫交互的相關操作,這本身應該算是對Model的一種弱化,實際上,參考微軟提供的MVCScore的示例項目(
下載鏈接)可以發現,Model並不是通常意義上跟數據庫中表的對應,對應的其實是后台的Service這部分,Model作為業務邏輯模型,應該承擔更多業務處理工作,這樣才是把業務和頁面展示分開,實現前台頁面和后台邏輯的解耦。
當然,軟件設計模式不是標准,只是一個解決特定方案的相對合理化方案而已,解耦也不是軟件設計的唯一標准,甚至不是最重要的標准。
1.4MVP模式的一般實現方式
目前我的項目中的實現方式是用接口來連接view和Presenter,根據定義好的接口來進行分塊開發,如下圖:

接下來是做一個小的demo來實際明確一下各部分的功能:
2.MVP的demo
2.1這個demo的具體使用場景和簡單設計
我還是想把這個demo做成一個持續優化的項目,對於一個正式一點的項目,登錄頁面一般都是網站的第一步,這個demo就先做一個登錄頁面,暫時不考慮數據交互,MVP都定義最簡單的形式,獲取角色,輸入用戶名密碼,登錄。
2.2詳細設計
分模塊定義:
2.2.1 數據實體類項目(Data):添加角色類和用戶信息類
2.2.2 數據業務邏輯模型項目(Model):添加一個登錄驗證類,添加獲取角色信息和用戶登錄兩個方法
2.2.3 界面業務邏輯操作項目(Presenter):這里有兩部分的內容:1.接口定義;2.頁面處理邏輯。通過定義委托和接口中的屬性來控制頁面上的事件和數據。
以前一直以為Model包括Data和Dao,所以一直不理解,為什么說Model和View沒有通訊,實體類肯定是貫穿整個解決方案的,view就不說了。
2.3各個部分的實現
Data項目:

public class RoleInfo { public string RoleName { get; set; } public string RoleID { get; set; } }

public class UserInfo { public string RoleID { get; set; } public string UserName { get; set; } public string Password { get; set; } }
Model項目:

/// <summary> /// 權限管理 /// </summary> public class Authority { /// <summary> /// 初始化方法 /// </summary> public IList<RoleInfo> GetRoleList() { IList<RoleInfo> roleList = new List<RoleInfo>(); roleList.Add(new RoleInfo() { RoleName = "管理員", RoleID = "1" }); roleList.Add(new RoleInfo() { RoleName = "操作員", RoleID = "2" }); roleList.Add(new RoleInfo() { RoleName = "一般用戶", RoleID = "3" }); roleList.Add(new RoleInfo() { RoleName = "VIP用戶", RoleID = "4" }); return roleList; } public bool Login(string userName, string password) { return true; } }
Presenter項目:

public delegate bool LoginEvnet(string userName,string password); /// <summary> /// 登錄窗口需要實現的接口 /// </summary> public interface ILoginView { IList<RoleInfo> RoleList { set; } }

/// <summary> /// 權限管理 /// </summary> public class LoginPresenter { private ILoginView _view; private Model.Authority authority; public LoginPresenter(ILoginView view) { _view = view; authority = new Model.Authority(); } /// <summary> /// 登錄方法 /// </summary> /// <param name="userName"></param> /// <param name="password"></param> /// <returns></returns> public bool Login(string userName,string password) { return authority.Login(userName,password); } /// <summary> /// 初始化方法 /// </summary> public void Init() { _view.RoleList = authority.GetRoleList(); } }
頁面后台代碼,負責綁定事件和更新頁面控件屬性:

public partial class LoginView : System.Web.UI.Page, ILoginView { private LoginPresenter presenter; protected void Page_Load(object sender, EventArgs e) { presenter = new LoginPresenter(this); presenter.Init(); btnLogin.Click += delegate { if (presenter.Login(txtUserName.Value, txtPassword.Value)) { //登錄成功 this.ClientScript.RegisterStartupScript(typeof(string), "js", "alert('登錄成功!');", true); } else { this.ClientScript.RegisterStartupScript(typeof(string), "js", "alert('登錄失敗!');", true); } }; } public IList<RoleInfo> RoleList { set { foreach (RoleInfo text in value) { ListItem item = new ListItem(); item.Text = text.RoleName; item.Value = text.RoleID; ddlRole.Items.Add(item); } } } }
最后說一點,這周公司內部培訓,接觸了下struts2的框架,相比之下,突然覺得MVP只是一個概念,實際上用的時候並沒有真正用到任何所謂的框架,MVP夾在MVC和MVVM之間感覺定位也是有點尷尬,就我目前的理解來說,MVP是一種關注代碼分離的設計思想,還是不如MVVM分離的干凈。