说到MVP模式就不得不说MVC模式,MVP其实是MVC的一个变体模式,那先说下这两者区别.

在MVP中View并不直接使用Model,它们之间的通信是通过Presenter(MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过Controller。

Model和View是完全隔离,由Presenter来完全Model和View之间的交互行为.

在MVC中虽然是通过Cotroller,但是View是可以直接访问Model的,从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示及View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。

这样看MVP的优点是非常明显的,但是这种模式就会导致View与Presenter之间产生的依赖就会比较大,如果View变化,可能就会导致Presenter变化,那这个有没有办法去降低这种依赖呢.

首先看下MVP的模型图

2010012820045716

下面直接开始MVP的代码.

namespace MVPSimple.Model
{
    public class CashBond
    {
       public string BondCode{ get; set; }

       public decimal ClearPrice{ get; set; }

       public decimal Total{ get; set; }

    }

    public class CashBondService
    {
        List<CashBond> cashBonds = new List<CashBond>();
        public CashBondService()
        {     

        }

        public CashBond GetCashBondByBondCode(string bondCode)
        {
             CashBond cash = //调用数据访问层,将数据提取出来
             return cash;
        }

        public List<CashBond> GetAllCashBond()
        {
            //调用数据访问层,将数据提取出来
            return cashBonds;
        }

    }

}

   public interface ICurrentView
   {
       void AddAllCashBond(List<CashBond> cashs)
       void RemoveCashBond(string bondCode)
   }

   public class Presenter
    {
        private ICurrentView view;
        public Presenter(ICurrentView _view)
        {
            view = _view;
        }

        public void AddAllCashBondAction(string bondCode)
        {

             CashBondService service = new CashBondService()
             List<CashBond> cashs = service.GetAllCashBond()
             view.AddAllCashBond(cashs)
        }

    }

    public class CurrentForm : Form, ICurrentView
    {
        private Presenter presenter;
        public CurrentPage()
        {
            this.presenter = new Presenter(this);
        }

        public void AddAllCashBond(List<CashBond> cashs)
        {
           ListViewItem item = null;
           foreach(var cash in cashs)
           {
              item = new ListViewItem();             
              item.Text = cash.BondCode; 
              item.SubItems.Add(cash.ClearPrice.ToString()); 
              item.SubItems.Add(cash.Total.ToString()); 
              this.lv.Items.Add(item);
           }

        }

        public void RemoveCashBond(string bondCode)
        {
            //do something
        }

        private void btnBind_Click(object sender, EventArgs e) 
        { 
           this.presenter.AddAllCashBondAction(); 
        }

    }

上面的代码就是MVP的"标准"实现方式.在我理解中,MVP就是采用的中介者模式,将对象与对象之间的关联关系解耦,变"多个对象互相关联"为"多个对象和一个中介者关联".

但是大家看到其实View与Presenter还是有较大关联,在View中还是需要访问Presenter对象,那如何将各对象不直接和中介者进行耦合呢,也就是尽量弱化(不可能完全剔除)

View对Presenter的依赖。实际上,对于MVP来说,View仅仅向Presenter递交用户交互请求,使View无法直接显示访问Presenter以及Presenter成员.这通过事件订阅机制就可以了.

下面来扩展上面的代码.

public class CashBond : ICloneable
 {
       public string BondCode{ get; set; }
       public decimal ClearPrice{ get; set; }
       public decimal Total{ get; set; }

       object ICloneable.Clone() 
       { 
          return this.Clone(); 
       } 

       public CashBond Clone() 
       { 
          return new CashBond 
          { 
             BondCode = this.BondCode, 
             ClearPrice = this.ClearPrice, 
             Total = this.Total
          }; 

       }

    }

    public class CashBondViewModel
    {
        List<CashBond> cashBonds = new List<CashBond>()
        {
             new CashBond{ BondCode= "001", ClearPrice= "100.00", Total= "1000000.00"}, 
             new CashBond{ BondCode= "002", ClearPrice= "99.00", Total= "2000000.00"}
        }

        public CashBondViewModel()
        {     

        }

        public CashBond GetCashBondByBondCode(string bondCode)
        {

             var cashs = from cash in cashBonds 

                         where cash.BondCode = bondCode

                         select cash.Clone();

             return cashs.ToList<CashBond>()[0];

        }

        public List<CashBond> GetAllCashBond()
        {
            var cashs = from cash in cashBonds 

                         select cash.Clone();

             return cashs.ToList<CashBond>();
        }

    }


    public interface ICashBondView{ 

        event EventHandler Load;
        event EventHandler<CashBondEventArgs> CashBondSelected;  //定义了单条选择的事件,这个事件很重要

        void ListAllCashBonds(List<CashBond> cashs); 
        void DisplayCashBondInfo(CashBond cash); 
        void Reset(); 

     }


    public class CashBondEventArgs : EventArgs   //继承EventArgs基类,以便于传参 
    { 
       public string BondCode
       { get; set; } 

       public CashBond Cash
       { get; set; } 

     }

     public class Presenter<IView> 
     { 
         public IView View { get; private set; } 
         public Presenter(IView view) 
         { 
            this.View = view; 
            this.OnViewSet(); 
         } 

         protected virtual void OnViewSet()  //此方法需要重写,注册各种事件
         { } 

      }

      public class CashBondPresenter : Presenter<ICashBondView>
      {
          public CashBondViewModel viewModel{ get; private set; }
          public CashBondPresenter(ICashBondView cashView)
             : base(cashView)
          {
             this.viewModel = new CashBondViewModel();
          }

          protected override void OnViewSet()  //重写并注册事件,一旦View中触发,就会执行里面的方法
          {
              this.View.Load += (sender, e) => {
              List<CashBond> cashs = viewModel.GetAllCashBond();
                   this.View.ListAllCashBonds(cashs);
              };

              this.View.CashBondSelected += (sender, e) => {
                 CashBond cash = viewModel.GetCashBondByBondCode(e.BondCode);
                 this.View.DisplayCashBondInfo(cash);
             }

          }        

      } 

   public partial class ViewBase : Form 
   { 
       private object _presenter; 
       public ViewBase() 
       {  
          _presenter = this.CreatePresenter();  
       } 

       protected virtual object CreatePresenter() 
       {
           return null; 
       } 

    }

    public class CashBondView : ViewBase, ICashBondView
    {
        public CashBondView()
        {
            return new CashBondPresenter(this);
        }

        public event EventHandler<CashBondEventArgs> CashBondSelected; 
        public void ListAllCashBonds(List<CashBond> cashs)
        {
            this.dgvCashBond.DataSource = cashs;
        }

        public void DisplayCashBondInfo(CashBond cash) 
        { 
            //do something 
        }

        public void Reset() 
        { 
            //do something 
        }

        protected virtual void OnCashBondSelected(string bondCode) 
        { 
            var prebondCode= this.textCashBondCode.Text.Trim(); 

            if (bondCode == prebondCode) 
               return; 

            if (null != this.CashBondSelected) 
               this.CashBondSelected(this, new CashBondEventArgs { BondCode = bondCode}); 

         }

         private void dgvCashBond_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) 
         { 
             var currentRow = this.dgvCashBond.Rows[e.RowIndex]; 
             var bondCode = currentRow.Cells[0].Value.ToString(); 
             this.OnCashBondSelected(bondCode); 

         }

    }

 

posted on 2013-09-12 16:54  tzj19810812  阅读(262)  评论(1)    收藏  举报