前端MV*框架之MVP

作者: integrate | 来源:发表于2015-09-22 00:02 被阅读2118次

    一、学习背景

    本文是继“前端MV*框架之经典MVC”的第二篇,学习动机是通过深入理解MVC、MVP、MVVM后,找到适合backbone.js框架的最佳实践。

    二、MVP历史简介

    MVP(model-view-presenter)由经典MVC演变而来,起源于20世纪90年代的Taligent公司(IBM子公司)。得益于Taligent公司的CTO(Mike Potel)在一篇论文中的推广而普及开来。在1997年,开发Dolphin Smalltalk的工程师改造了原始的MVP模式,用于重构Smalltalk的用户界面框架。在2006年,微软将MVP模式纳入开发文档,用来开发.NET framework环境下的图形用户界面。

    三、MVP的由来

    看了下Mike Potel介绍MVP的论文,发现原始的MVP模式与如今大家公认的MVP模式相差甚远,与经典MVC有着相同的境遇:已经被废弃,不再使用。如今被广泛应用的是演变后的MVP。接下来,通过流程图的方式来说明经典MVC是如何进化为原始MVP的:

    "经典MVC 进化为 原始MVP""经典MVC 进化为 原始MVP"

    对于V与M的调用关系存在一种误解:“发送状态通知的逻辑一定写在M里,调用M进行重新渲染的逻辑一定写在V里”。我们知道M与V是通过观察者模式建立的关系,而建立这套关系的逻辑应该是具体的MV*框架的底层实现,并不归属于M或者V。

    首先回顾一下经典MVC的样子:

    一对C-V捆绑起来表示一个ui组件,C直接接受用户输入,并将输入转为相应命令来调用M的接口,对M的状态进行修改,最后通过观察者模式对V进行重新渲染。

    进化为MVP的切入点是修改C-V的捆绑关系,为了解决C-V的捆绑关系,将V进行改造,使V不仅拥有UI组件的结构,还拥有接受用户刺激的能力,这样就能将C独立出来。为了对用户的刺激进行统一管理,V只负责将用户产生的事件传递给C,由C来统一处理,这样的好处是多个V可共用同一个C,成功将原来的两个阵营(M、C-V)分解成三个阵营(M、V、C)。此时的C也由组件级别上升到了应用级别,然而更新V的方式仍然与经典MVC一样:通过C更新M,通过观察者模式更新V,为了区别于经典MVC,把这种模式叫作MVP。最初的MVP就是这个样子的,它仍然没有对第一篇中MVC的短板给出解决方案,但仍然是进化中必不可少的一步,这一步是由Taligent公司完成的。

    四、原始MVP进化为MVP(Supervising Controller)

    1997年,开发Dolphin Smalltalk的工程师对原始的MVP进行了改造,终于对经典MVC的短板给出了具体的解决方案。MVP的改造过程如下图所示:

    "原始MVP 进化为 MVP(Supervising Controller)""原始MVP 进化为 MVP(Supervising Controller)"
    改造后的MVP对V的渲染采用了两种方案:
    1. 对于简单的渲染(无需对model数据进行格式转化),仍然通过传统的观察者模式完成。
    2. 对于复杂的渲染,由Presenter来完成,比如设置Model数据的颜色、转化状态字段(0、1)的含义等复杂的表现层逻辑。

    此时Presenter负责两个方面:接受由V传递过来的用户事件、处理复杂的表现层逻辑;此时的Presenter也被称为:Supervising Controller。

    下面我将详细说明MVP(Supervising Controller)示意图中每条连线的含义:

    • 线路A、线路B与原始MVP中的含义一样:V通过观察者模式观察M,当M状态改变时发送通知给V(线路A),V接到通知后调用M的接口进行重新渲染(线路B)。
    • 线路C与原始MVP中的含义一样:接受由V传递过来的事件。
    • 线路D表示通过P对V进行复杂的渲染。
    • 线路E表示M与P建立了观察者模式,当M中的状态改变并且需要执行复杂的渲染逻辑时,M不会通知V,改为通知P,由P调用M的接口(线路F)获取基础数据,进行加工后渲染给V(线路D)。
    • 线路F表示P调用M的接口,对M中的数据执行读取或修改操作。

    五、受人追捧的MVP变种-MVP(Passive View)

    对于复杂的GUI应用来说,MVP(Supervising Controller)已经能够满足开发者的需求,为什么还会出现MVP(Passive View)呢?原因是为了满足自动化测试的需求,编写可测试的代码不知何时已经成为一种时尚,还有一系列基于测试的理念变的越来越流行:自动化回归测试、测试驱动开发、持续集成等。对于GUI应用来说,View层是很难实现自动化测试的,因为你不仅要测试View的结构、样式,还要模拟用户的交互行为。对于MVP模式来说,Presenter是可以实现自动化测试的,所以人们开始尽可能的将应用逻辑放到Presenter中,导致原本不属于Presenter的"简单渲染逻辑"也被加入Presenter中,形成了一种新的MVP变种-MVP(Passive View):

    "MVP(Passive View)""MVP(Passive View)"
    为了将全部的表现层逻辑交给Presenter,删除了M与V基于观察者模式建立的映射关系,不管是简单的渲染还是复杂的渲染,统统交给Presenter来实现,这么做的代价是Presenter层变的非常庞大,尽管如此,MVP(Passive View)依然成为最流行的MVP变种,以至于当我们谈论MVP模式时,暗指的就是MVP(Passive View)模式。

    六、总结

    总体来说,MVP首先由经典MVC演变而来,将应用程序划分为真正的三层结构,然后进化为MVP(Supervising Controller)满足了开发复杂GUI应用的需求,最后由于自动化测试的驱动演变为MVP(Passive View)。

    参考文献:

    <a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter">wiki mvp</a>
    <a href="http://martinfowler.com/eaaDev/uiArchs.html#Model-view-presentermvp">Martin Fowler mvp</a>
    <a href="http://martinfowler.com/eaaDev/uiArchs.html#HumbleView">Martin Fowler HumbleView</a>
    <a href="http://www.wildcrest.com/Potel/Portfolio/mvp.pdf">Mike Potel mvp</a>

    相关文章

      网友评论

      • bbf5fa536219:这是我第二次看别人的文章给赞了,你的综合水平应该很强,不知道能否给个qq,以后多多交流,我的qq是609210276
        integrate: @wolovexs 332574253 加我的群吧
      • flypatrickg:感谢作者,这篇文章是我看到过的关于MV*的文章里面最深入浅出的一篇。期待拜读作者的后续文章。
        integrate:@flypatrickg 第一次有人给我打赏啊,多谢支持与鼓励,很高兴文章对你有用
      • SeanKChan:马克,

      本文标题:前端MV*框架之MVP

      本文链接:https://www.haomeiwen.com/subject/lsficttx.html