MVP架构

MVP全称:Model-View-Presenter ;MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

如果你经常使用MVC,可能会不理解MVP,MVP用在安卓开发,桌面开发比较多。对于Model和View层,它们和MVC没什么区别。但是对于Presenter:

一个View页面/界面,我们都会安排一个Presenter,页面和Presenter相互关联。如何相互关联呢?

一般我们会在UI层定义一个接口类,这个类包括我们页面的一些属性和行为,比如文本展示,点击事件等。而我们的Presenter会实现这些接口,并和UI对象绑定,UI的任何行为都将与Presenter里的方法绑定在一起,UI点击行为会触发Presenter根据接口所实现的行为方法。

 

下面是MVP模式在窗体应用程序中的使用:参考

做过.net的winform和WPF开发的可能很好理解这个过程。

第一步,给每个view窗体,约定好一个接口

public interface IMemoFormView {
  String Title { get; set; }
  String Summary { get; set; }
  String Location { get; set; }
  String Tags { get; set; }
  DateTime BeginWithin { get; set; }
  DateTime DueBy { get; set; }
  String Message { get; set; }

  Int32 GetSelectedPriorityValue();
  void FillPriorityList(Int32 selectedIndex);
  Boolean Confirm(String message, String title);
  void SetErrorMessage(String controlName);
}

第二部,视图类实现约定的接口,实现接口。

public partial class MemoForm : Form, IMemoFormView {
  public string Title {
    get { return memoForm_Text.Text; }
    set { memoForm_Text.Text = value; }
    ...
}

  public DateTime DueBy {
    get { return memoForm_DueBy.Value; }
    set { memoForm_DueBy.Value = value; }
  }

  public int GetSelectedPriorityValue() {
    var priority = 
      memoForm_Priority.SelectedItem as PriorityItem;
    if (priority == null)
      return PriorityItem.Default;
    return priority.Value;
  }

  public void FillPriorityList(int selectedIndex) {
    memoForm_Priority.DataSource = 
      PriorityItem.GetStandardList();
    memoForm_Priority.ValueMember = "Value";
    memoForm_Priority.DisplayMember = "Text";
    memoForm_Priority.SelectedIndex = selectedIndex;
  }

  public void SetErrorMessage(string controlName) {
    var control = this.GetControlFromId(controlName);
    if (control == null)
      throw new NullReferenceException(
        "Unexpected null reference for a form control."); 

    memoForm_ErrorManager.SetError(control, 
      ErrorMessages.RequiredField);
  }

  ...
}

第三步,窗体类初始化时创建Presenter对象,并将自己传递给Presenter,此时窗体创建的时候就和Presenter绑定起来了。

public partial class MemoForm : Form, IMemoFormView

  private MemoFormPresenter presenter;

  public Form1() {
    // Framework initialization stuff
    InitializeComponent();
    // Instantiate the presenter
    presenter = new MemoFormPresenter(this);
    // Attach event handlers
    ...
}

  private void MemoForm_Load(
    object sender, EventArgs e) {

    presenter.Initialize();
  }
  ...
}

第四步,Presenter类在初始化的时候会拿到我们实现的窗体对象memoForm

public class MemoFormPresenter {
  private readonly IMemoFormView view;

  public MemoFormPresenter(IMemoFormView theView) {
    view = theView;
    context = AppContext.Navigator.Argument 
      as MemoFormContext;
    if (_context == null)
      return;
  }
 
  public void Initialize() {
    InitializeInternal();
  }

  private void InitializeInternal() {
    int priorityIndex = _context.Memo.Priority;
    if (priorityIndex >= 1 && priorityIndex <= 5)
      priorityIndex--;
    else
      priorityIndex = 2;

    if (_context.Memo.BeginDate.HasValue)
      _view.BeginWithin = _context.Memo.BeginDate.Value;
    if (_context.Memo.EndDate.HasValue)
      _view.DueBy = _context.Memo.EndDate.Value;
      _view.FillPriorityList(priorityIndex);
      _view.Title = _context.Memo.Title;
      _view.Summary = _context.Memo.Summary;
      _view.Tags = _context.Memo.Tags;
      _view.MemoLocation = _context.Memo.Location;
  }
  ...
}

这样,页面初始化,我们会经过Presenter的InitializeInternal,将数据set到对应view所绑定的UI字段上。