myRoad—关于MVP模式

一,MVP模式

认识MVP模式是通过读artech的文章,在工作中使用MVP模式也是时刻想着他翻译的的CAB(Componsable Application Block)基于14条MVP规则:

 

  • 所有的View(包括View的接口)的名称应该以View作为后缀,比如TaskView/ITaskView;
  • 所有的Presenter名称应该以Presenter作为后缀,比如TaskViewPresenter;
  • Presenter完成Use Case处理逻辑,对GUI控件的处理应该在View中实现;
  • View调用Presenter的方法应该像触发事件异常,通过调用OnXxx方法的方式来实现;
  • 应该尽可能地限制View对Presenter的调用,并且调用的方式限于按照“事件”的形式,比如_presenter.OnViewReady();
  • View不允许通过Presenter直接调用Model和Service,并且Presenter的方法应该是不具有返回值的;
  • Presenter必须通过View接口的方式调用View
  • 除了对View接口成员的实现外,View中的其他方法不应该是public的;
  • 除了CAB ModuleController 对View的加载和限制外,View只能被Presenter调用;
  • View接口方法应该基于Use Case的逻辑起一个有意义的名称,比如SetDataSource这样的方法名称是不合法的;
  • View接口的成员应该仅限于方法,不应该包含属性;
  • 所有的数据应用保持在Model中
  • 定义在View接口的方法不应该包含对GUI空间名称的引用(比如AddExplorerBarGroup),因为这会使Presenter知道View太多关于实现方面的细节;
  • 尽量让View的方法名称反映Use Case的业务逻辑,这样可以使你的代码具有自表述性并更加易于理解。
  •  

二,工作中遇到的问题

 

1.工作中使用到MVP模式,在我的认识中MVP的写法是下面这样的:

 
IView,定义View的事件,和View必须实现的方法 :
 
    public interface ITestView
    {
        event Action SomeEvent;
        void ShowMessage(string msg);
    }
 
View,实现IView,并且在构造函数里初始化Presenter :
 
    public partial class TestView : Window,ITestView
    {
        TestPresenter presenter;

        public TestView()
        {
            InitializeComponent();

            presenter = new TestPresenter(this);

            this.btnSomething.Click += (sender, e) =>
                {
                    if (this.SomeEvent != null) SomeEvent();
                };
        }

        #region ITestView 成员

         public event Action SomeEvent;

        public void ShowMessage(string msg)
        {
            MessageBox.Show(msg);
        }

        #endregion
    }
Presenter构造函数需要一个实现了Iview接口的View,并绑定IView里的事件,进行处理后调用IView里定义的方法
 
    public class TestPresenter
    {
        public TestPresenter(ITestView view)
        {
            view.SomeEvent += () =>
                {
                    view.ShowMessage("MVP模式的测试");
                };
        }
    }

2.但是在工作中我们实际写的MVP模式是下面这种:

 

IView,只定义View的事件:

 

    public interface ITestView
    {
        event Action SomeEvent;
    }
 
View,实现IView,并且在构造函数里初始化Presenter,并且绑定Presenter里的事件 :
 
    public partial class TestView : Window,ITestView
    {
        TestPresenter presenter;

        public TestView()
        {
            InitializeComponent();

            presenter = new TestPresenter(this);

            presenter.ShowMessage += (msg) =>
                {
                    MessageBox.Show(msg);
                };

            this.btnSomething.Click += (sender, e) =>
                {
                    if (this.SomeEvent != null) SomeEvent();
                };
        }

        #region ITestView 成员

        public event Action SomeEvent;

        #endregion
    }
Presenter构造函数需要一个实现了Iview接口的View,并绑定IView里的事件,进行处理后调用自己定义的触发自己事件的方法:

    public class TestPresenter
    {
        public event Action<string> ShowMessage;

        private void OnShowMessage(string msg)
        {
            if (ShowMessage != null) ShowMessage(msg);
        }

        public TestPresenter(ITestView view)
        {
            view.SomeEvent += () =>
                {
                    OnShowMessage("MVP模式测试");
                };
        }
    }

 

三,自己对着两种写法的认识:

 

     第一种方法,IView需要定义用户可能会触发的事件,并且需要提供一些方法。

     我的理解是这样的IView相当清楚自己会怎么样,并且还知道自己能干什么,什么自己干不了。编写View的时候只要完成IView里定义的事件,并且把IView里定义的“能干的事情”都实现,不需要去关注Presenter里到底会怎么样。

     编写Presenter的人清楚的知道View能干什么事情,会触发什么事件。知道处理一些业务逻辑后自己该怎样去指挥View。

     自己感觉这样的方法,主控权是Presenter。View只是去执行,而且必须执行,没有选择权。(因为View继承IView接口,必须实现IView里定义的方法)

     第二种方法,IView只定义用户可能会触发的事件。

      我的理解是这样的IView只知道自己会怎么样,并不知道自己能干什么。编写View的时候需要要完成IView里定义的事件,并且需要清楚Presenter会发生什么样的事件,我要不要处理Presenter里发生的事件。

     编写Presenter的人不知道View能干什么事情,当接受到View发生的事件后,处理一些业务逻辑后,只是触发自己的事件,View层处理不处理,Presenter就不关心了。

     自己感觉这样的方法,Presenter 和 View 都回去控制一些东西,View有了选择权。(因为View可以监听Presenter的事件,也可以不监听)。

    

四,想向大家请教一些问题:

      自己老感觉MVP模式应该是第一种写法,但是和我们项目中用到的不一样,而且思想上好像有很大的差别,希望大家能给我一些指导,

第二种方法有什么好处? 真正的MVP模式处理这种问题应该是怎么写的?

posted @ 2011-02-26 19:00  风枫峰  阅读(1584)  评论(6编辑  收藏  举报