MVC 是一種Pattern 另一種說法是ParaDigm 範例html
模式和範例的區別在於前者能夠應用到具體的應用上,然後者則僅僅提供一些指導方針架構
Model View Presenter 交互圖測試
MVC 模式中元素之間 「混亂」的交互主要體如今容許View 和 Model 繞開Controller進行單獨交流,這在MVP 模式中獲得了充分解決ui
解決View很難測試的最好方法是讓他無需測試,讓UI處理更少邏輯,被動的交給Presenter來處理this
暴漏UI不必定必須暴漏UI控件,spa
沒有必要寫成3d
public interface IemployeeSearchView1 { DropDownList Department { get; } GridView Employees { get; } }
而能夠經過數據的屬性來定義接口,這樣就能夠將presenter中的UI處理邏輯分離出來code
public interface IemployeeSearchView { IEnumerable<string> Departments { set; } string SelectedDedpartment { get; } IEnumerable<Employee> Employees { set; } }
具體的實現方法以下:orm
public partial class _Default : System.Web.UI.Page, IemployeeSearchView { protected void Page_Load(object sender, EventArgs e) { } public IEnumerable<string> Departments { set { this.DropDownListDepartments.DataSource = value; this.DropDownListDepartments.DataBind(); } } public string SelectedDedpartment { get { return this.DropDownListDepartments.SelectedValue; } } public IEnumerable<Employee> Employees { set { this.GridViewEmployees.DataSource = value; this.GridViewEmployees.DataBind(); } } }
這樣作意味着全部的UI邏輯均可以被測試,可是它要求將全部可供操做的UI元素定義在對應的接口中,無疑會增長Presenter 的複雜度,這就引出SC模式server
View 和Presenter 之間的交互式整個MVP的核心,可否正確地應用MVP模式來架構應用,主要取決於View 和Presenter 之間的關係 在由model、View Presenter 組成的三角關係中,核心不是View 而是Presenter,Presenter 不只是View調用的中介,而是最終決定如何響應用戶交互行爲的決策者。
View 自己僅僅實現單純的獨立的UI處理邏輯,他處理的數據應該是Presneter實時推送過來的,因此View 儘量不去維護數據狀態,定義在IView的接口最好只包含方法,而避免屬性的定義,Presenter 所需的關於View的狀態應該在接收到View發送的用戶請求時一次性推送,而不須要經過View 的屬性去得到它
如下爲全部代碼
public class Employee { public string Id { get; private set; } public string Name { get; private set; } public string Gender { get; private set; } public DateTime BirthDate { get; private set; } public string Department { get; private set; } public Employee(string id, string name, string gender, DateTime birthDate, string department) { this.Id = id; this.Name = name; this.Gender = gender; this.BirthDate = birthDate; this.Department = department; } }
EmployeeRespository
public class EmployeeRepository { private static IList<Employee> employees; static EmployeeRepository() { employees = new List<Employee>(); employees.Add(new Employee("001", "張三", "男", new DateTime(1981, 8, 1), "銷售部")); employees.Add(new Employee("001", "李四", "女", new DateTime(1982, 8, 4), "人事部")); employees.Add(new Employee("001", "王五", "男", new DateTime(1981, 9, 1), "人事部")); } public IEnumerable<Employee> GetEmployees(string department = "") { if (string.IsNullOrEmpty(department)) { return employees; } return employees.Where(e => e.Department == department).ToArray(); } }
IEmployeeSearchView
public interface IEmployeeSearchView { void BindEmployees(IEnumerable<Employee> employees); void BindDepartments(IEnumerable<string> departments); } public class DepartMentSelectedEventArgs : EventArgs { public string Department { get; private set; } public DepartMentSelectedEventArgs(string department) { this.Department = department; } }
EmployeeSearchPresenter
public class EmployeeSearchPresenter { public IEmployeeSearchView View { get; private set; } public EmployeeRepository Repository { get; private set; } public EmployeeSearchPresenter(IEmployeeSearchView view) { this.View = view; this.Repository = new EmployeeRepository(); view.DepartmentSelected += view_DepartmentSelected; } public void Initialize() { var employees = this.Repository.GetEmployees(); this.View.BindEmployees(employees); string[] departments = new string[] { "銷售部", "人事部", "IT部" }; this.View.BindDepartments(departments); } void view_DepartmentSelected(object sender, DepartMentSelectedEventArgs e) { string department = e.Department; var employees = Repository.GetEmployees(department); this.View.BindEmployees(employees); } }
Web
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Chaper1SC.WebForm1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div id="page"> <div style="text-align: center; clear: both"> 請選擇部門:<asp:DropDownList ID="dpDownListDepartments" runat="server"></asp:DropDownList><asp:Button Text="查詢" runat="server" OnClick="Unnamed_Click" /> </div> <div> <asp:GridView ID="GvEmployees" runat="server" AutoGenerateColumns="false" Width="100%"> <Columns> <asp:BoundField DataField="Name" HeaderText="姓名" /> <asp:BoundField DataField="Gender" HeaderText="性別" /> <asp:BoundField DataField="BirthDate" HeaderText="出生日期" DataFormatString="{0:dd/MM/yy}" /> <asp:BoundField DataField="Gender" HeaderText="性別" /> </Columns> </asp:GridView> </div> </div> </form> </body> </html>
public partial class WebForm1 : System.Web.UI.Page, IEmployeeSearchView { public event EventHandler<DepartMentSelectedEventArgs> DepartmentSelected; public EmployeeSearchPresenter Presenter { get; private set; } public WebForm1() { this.Presenter = new EmployeeSearchPresenter(this); } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { this.Presenter.Initialize(); } } public void BindEmployees(IEnumerable<Employee> employees) { this.GvEmployees.DataSource = employees; this.GvEmployees.DataBind(); } public void BindDepartments(IEnumerable<string> departments) { this.dpDownListDepartments.DataSource = departments; this.dpDownListDepartments.DataBind(); } protected void Unnamed_Click(object sender, EventArgs e) { string deparment = this.dpDownListDepartments.SelectedValue; DepartMentSelectedEventArgs args = new DepartMentSelectedEventArgs(deparment); if (null != DepartmentSelected) { DepartmentSelected(sender, args); } } }