这本书的实际价值也许还值得商榷。毕竟它并没有提出任何前所未有的算法或者编程技术。它也没能给出任何严格的系统设计方法或者新的设计开发理论——它只是对现有设计成果的一种审视。大家当然可以将其视为一套不错的教程,但它显然无法为经验丰富的面向对象设计人员带来多少帮助。
摘自GoF《设计模式:可复用面向对象软件的基础》的最后一章
目录
快速回顾
MVP那些事儿(4)……在Android中使用MVC(下) MVC的各个组件通过一些规则已经组合完成,同时加入了监听机制,组成一条高效的事件传送带,让事件流转其中,在未来,我们可以在这条带子上关键环节加入多个处理事件的方法,并把它们暴露出来供使用者自定义它们的具体功能,让其扩展最大化。
MVP
我们之前已经通过大量的篇幅详细的介绍了MVC架构,同时也开始着手搭建一个框架,目的是就是为了可以平滑的过渡到MVP,如果你对MVC架构基本概念的理解有些模糊,或一知半解,不妨回头耐心的看看之前的章节,毕竟MVC有很多部分是和MVP有共通性的,比如View和Model的职责等等这些,都与MVP是息息相关的,而本章的内容是将注意力放在它们之间的不同点上,不会过多的阐述它们之间共通的部分。如果已经阅读了的朋友,结合本章内容你会很轻松的理解并抓住MVP的本质。
中介者模式(Mediator)
为了能更好的理解MVC与MVP的区别,就要把它们具象的去讨论,而不是简单的停留在抽象的层面。MVP的出现一定是解决了MVC某一方面的不足,必然算是一种提升,而这提升的过程,必然也是思想的提升,但凡涉及到设计思想,也就逃不出大众的思维,我们在处理一些问题时,都会碰到一些阻碍,人们在处理这些问题时为了能造福后代,少走弯路,就把这些经验流传下来,古有三十六计孙子兵法,今有GoF的二十三种设计模式,都是为了解决一些场景性的问题而制定的最优策略。所以,在MVC提升到MVP的过程中,会不会也有前人留下的设计思想值得我们去借鉴一下呢?在我学习MVP的时候,我发现了中介者设计模式与MVP的核心思想有很大程度的吻合,也特别想从中介者模式的这个角度去谈谈MVC与MVP之间的本质区别,其主要目的还是希望能通过一个具象的例子,延伸到抽象的架构上去,加深理解,所以理解了中介者模式也就更容易去理解MVP。
中介者模式的出现是为了解决对象间复杂的引用关系。为了快速get到中介者模式的核心价值,我们引入一个场景。
场景
假设你是一个项目组的开发人员,你的角色是开发,你有很多同事,他们分别为,设计,美工,后台,需求,测试。
同事类(Colleague)
你可以把你的同事看成一个个的类,从你做为出发点,你的同事统一称之为同事类,你在别的同事眼中也是他们的同事类,你们是一类人,都可以叫做同事类,
场景描述
由于是新的项目,项目经理没有到位,同事间沟通全都是点对点,相对比较混乱,没有人负责流程。在项目进行中,项目经理到岗,他决定,所有的沟通都要先汇报到项目经理,然后再让项目经理转发命令到相应的同事。比如产品经理提出一个新的想法,先要传递到项目经理处,再由项目经理决定,到底需要开发还是设计来参与这个需求,在这里,项目经理承担着中介者的职责,他相对于同事类来说就是中介者类。中介者设计模式只涉及到两个角色,同事与中介者。
中介者的职责
首先,中介者的目的就是让同事类之间“永不相见”,也就是所谓的“隔离”。并负责收集传递同事间的事件,在此期间做一些流程控制。
注意:设计不当,会使得中介者变的臃肿,不易维护。
同事类的职责
中介者的同事类可以是无数个,同事类也可以有共通的行为,比如上班,下班,吃中饭。同事类也可以完全没有共通行为,比如有一类同事,它们可能只负责编码,还有一类同事,它们可能只负责订饭,编码的不会订饭,订饭的也不会编码。
在了解中介者模式的使用场景后,我们通过一幅图来对比一下:
没有使用中介者
使用中介者
第一张图,所有的对象都包含其他的对象,对象间关系复杂。
第二张图,所有的对象只和中介者(项目经理)交互,由中介者负责处理逻辑和转发事件
那么中介者模式和MVP架构有什么联系吗? 我们把上面的两张图简化一下,还记得我们之前是怎么介绍MVC的架构图吗?没错,把具象的变成抽象的。
抽象化
我们首先把同事类的个数从5个变为3个:
深度解读
公司不可能只有一个程序员或者产品经理,更或者是项目经理(我们这里讨论的角色都是泛化前的,也就是接口)。举个例子,项目的过程中不知什么原因又换了一个项目经理,不管怎么换他的核心职责就是中介者,又或者换了一个程序员,他可能有他独有的特性,但核心还是一个会敲代码的同事类,在现实中,这种人员调动一定会存在的,如果大家都是点对点的沟通,那么耦合是在所难免,假设一个产品经理角色依赖了最少四个以上的其他同事,当这个产品不在了,或者需要替换,那么他们之间的行为都会消失无法利用。而有了中介者,同事间的沟通是不需要知道接受方是谁,这一切都由中介者去操心。而同事类也可以不用知道具体的中介类是谁,他们之间是绝对透明的,也许第二天你即时通讯软件里收到的信息是来自另外一个项目经理的指令,这也就是所谓的“封装/隔离”,也是接口的本质。
错综复杂的对象间关系
在中介者模式的章节里,我们知道这个模式的核心价值观是为了解决对象间错综复杂的关系,但除此之外,它还有一个非常酷的拓展能力,这也是MVP最为重要的一个能力——可复用与可扩展性。 复用性和可扩展性才是用好MVP的关键
MVP的扩展性
我们继续通过之前的场景来阐述MVP的扩展性,项目中一开始只开发了IOS平台的软件,这个时候公司决定增加Andoird平台,之前项目已经有了一个完整的团队,现在只需要加入一个Andoird程序员和一个熟悉Android设计的UI,因为IOS和Android程序员都有一个共同的能力,就是对接口理解,以及对设计和需求的理解是一致的,只不过他们使用的平台不一样,所以在泛化程序员的时候,我们只要把平台这一项放开即可,UI也是一样,他们使用的工具和设计稿相同,只不过切图的尺寸不同,而产品经理、项目经理、测试工程师、后台工程师都可以直接拿来复用,而不需要另外组建一个团队,这对公司来说是一件非常节省成本的事情,而同时,程序员组和UI组的到了能力扩展。 再继续举个例子,在项目的开展过程中,由于追赶进度,需要加班,而项目经理周六日无法加班,于是公司派了一个加班项目经理。他只有在周六日上班,由于是加班,所以加班项目经理决定下班时间从七点调整为五点,这样当项目处于加班期时,员工五点下班,我们的项目经理都有决定下班时间的功能,而这个功能是开放的。很不巧的是,我们的产品经理也需要一个加班产品经理,这个加班产品经理他根本不知道加班项目经理和项目经理之间的区别,他一直以为下班时间为五点,而事实上他无需关心,同样的,加班项目经理也不知道这个产品经理是个加班产品经理,他也无需关心这一点,他们之间永远都是透明的。 (仔细看这张图,慢慢体会)。
总结
我们看似是在讲中介者,其实只是通过中介者来论述MVP架构的优势, 中介者模式的出现是为了解决对象间错中复杂的关系,在没有中介者的情况下,所有对象都要认识彼此,有了中介者,它包含了整个系统的控制逻辑,中介者除了能解耦并增加对象复用外,还有以下几点好处
控制逻辑集中,职责明确让模块更加方便维护
那么MVP的出现就是为了解决MVC各个层间的一个强耦合以及扩展不灵活等问题。所以在MVP中,P可以是设计成为一个接口,M和V也可以设计成一个接口,这才能发挥MVP价值最大化。
我在刚接触设计时,由于理解不够,一上来不管三七二十一先接口化,甚至有专门的插件帮你生成接口文件,但很多时候事与愿违,整个项目到最后,接口的实现类也只用一个,甚至万年不变.
在这里多说一句,在使用MVP时,并不是都要接口化的,一定要按照实际情况去设计,如果真的只有存在一个实例,看似使用了MVP架构来做设计,但只是形似而已。这个时候要思考一下,项目是否到了需要考虑复用性和扩展性到的步了呢?还是,到不如把它们写成一团,反而少了一些不必要的类更易于阅读和维护。
说点题外话
最近加入新公司,年底部门招人,我又义不容辞的成了面试官,来面试的经验从两年到五年的七年以上的均有,三年以上的我基本都会问关于MVP和MVC的问题,可是能说明白的很少,即便说出来也还停留在使用层面,这其中还有的是teamleader,或项目负责人,如果这些级别的都不去考虑架构或一知半解,难道还要指望自己下面的小弟吗?这其实也是我对自己的担忧,我认为程序员做到一定的阶段,应该多去收集已知零散的知识点,对它们穿针引线,让它们相互产生关联,始终围绕在一套思想体系当中,让自己成为这套体系的受益人,并不断的改进和趋近完善,而在不断完善的过程中必然会吸收更多的知识(比起低素质,劈腿率高这些我无需证明,勤奋还是需要证明一下的)。