从零搭建Android框架Android-Tractor(三) 模式选择

来源:互联网 发布:sketch 46 破解版 mac 编辑:程序博客网 时间:2024/04/30 01:58

从零搭建Android框架Android-Tractor(三)
模式选择

在上一篇中,我们对程序的四个模块,提出了一些疑问,但是没有解答。在这篇,我们结合现有比较常见的前端架构模式,来看看它们是怎么解决这些问题,并寄希望找到一个比较适合的架构模式来设计我们的框架。这些代表性的模式是MVCMVPPresentation Model

在这篇文章中,我们不对这些架构模式做详细的介绍,如果有疑问可以参考这里。这三个模式都只有三部分,我把业务逻辑和外部数据放在模型里面,以方便探讨。按照上一篇的思路,它们俩的问题简单合并一下就是:

1.        谁,从哪,怎么得到模型改变?

2.         谁,怎么把模型,发送给谁?

MVC

MVC大家估计最熟悉了,不管是客户端开发还是后台,都有对应的MVC实现框架我们这里说的MVC是侧重客户端开发经典MVCSmalltalk-80MVCMVC由三部分组成:视图、控制器和模型。首先,我们来看看它是怎么解决操作识别相关问题的。


MVC中,控制器负责接收外部的输入,控制器和视图是一一对应的关系,控制器的层次关系和视图的层次关系一样,最外层有一个控制器,它负责接收用户输入,然后把这些输入向下传递到目标控制器上。目标控制器就根据输入以及当前视图的状态来得出操作意图,进而改变模型或者视图的状态。

接下来看模型:


MVC最大的贡献就是视图和模型分离,这个就是靠观察者模式来实现的,模型不需要知道视图(当然也不需要知道控制器),但是视图可以作为观察者,得到模型的变化。但是MVC中的模型并没有得到更深入的区分和职责分配。学习MVC的时候,大家最经常听说的一个词可能就是一个Model,多个视图,这是最理想的情况,但是现实却经常不是这样。对于不同的视图而言,它的业务逻辑可能是不一样的,外部数据却是一致的。为了保证模型的一致性,妥协的办法就是把大量的业务逻辑从模型中剥离,移植到控制器里面了。导致的后果就是控制器里什么都有,臃肿不堪。而控制器的初衷只是为了截获用户输入,获取操作意图而已,,并且由于控制器和视图是一一对应的,控制器最好能独立于业务逻辑,而保持一定的复用性。

最后,我们来看一下视图:


在上一篇文章里,我们把视图的显示分为两种,一种是内容,一种是皮肤。视图的内容通过观察者模式和模型保持一致即可。但是皮肤状态就有点麻烦,模型原则上是不应该有视图状态的,所以这个皮肤状态的管理又被转嫁给了控制器。这些状态包括,比如鼠标移过按钮的时候,按钮高亮显示、Toggle Button被选中的状态、按钮不可用的状态等等。这些状态和模型是没有关系的。但是有些情况,视图的皮肤状态和模型相关。比如上次提到过的文本控件,它显示的内容代表了成绩。假如有这样的逻辑,当成绩少于60的时候,文本字体颜色应该显示红色。该怎么处理呢?这个其实是很常见的情形。解决的办法有三种:

1在控制器里监控模型改变,然后调整控件字体颜色

2自定义新的控件,根据内容变化,自动改变颜色。

3改变模型,使得模型里有颜色相关属性。

这些办法都有问题。办法1更加重和滥用了控制器;办法2,增加了工作量,并且新控件也没什么复用性可言;办法3,原则问题,触动MVC的根本。

基于以上种种,MVC不是我们想要的。

MVP

MVC中,输入由控制器来接收,视图自己是不具备输入能力的。随着时代的发展,ViewController被封装在一起,作为标准控件,更具有通用性。现在,基本上所有的GUI开发都是基于标准控件的,从这层意思来说,MVC也已不适用了。在新的环境下,MVP诞生了!我们今天讲的MVP是比较成形,且具有代表性的Dolphin Smalltalk MVP。后来,Martin FowlerMVP进行了一些归纳和分类,演变成Passive ViewSupervising Controller 。它们和Dolphin Smalltalk MVP在数据同步上稍微有点差别,但核心思想差不多,我们主要看看Dolphin Smalltalk MVP就可以了。

还是先看操作识别部分:


MVP中,视图控件和Presenter的关系是多对1的关系,视图控件自己就能接收用户输入,并做出反应(比如改变视图的皮肤状态)。只有对应的操作的需要改变模型的时候,才把相关事件转发给Presenter

现在,我们继续来看看MVP的模型部分:


它和MVC的模型部分,几乎差不多。所以也存在MVC同样的问题,在实际的开发过程中,会让Presenter负担一部分程序相关的业务逻辑。但,还是可以接受的,因为Presenter本身就是Form级别的,本身和场景紧密相关,也不指望它可以重用。整体来说,PresenterMVC中的控制器,更适合用来作为操作识别,唯一的遗憾就是,在现实面前,它会承担部分的业务逻辑。

接着,我们来看看MVP的视图部分:


视图因为自己有接收输入的能力,所以自己可以负责一些用户输入相关的状态,但是对于其他的状态,还是没有较好的解决办法。还有一个问题就是,虽然视图得到了数据,但是这个数据如果类型不对怎么办呢?在MVP中,解决这个问题两个方向:

1视图支持多种类型

2模型根据视图所需,提供对应的类型。

这两种办法都不是很好,尤其2,根本不可以接受,那么1,也会造成大量的无用功,因为不知道模型数据类型的,所以需要支持所有的类型,才OK

PresentationModel

看见Presentation Model这个名字,我对它是抱有幻想的,终于有对Model进行分解的参考模式了。到底是不是这样,我们还是一步一步来,先看看它的操作识别部分。


Presentation Model模式也包括三部分,分别是: ViewPresentation ModelModel。在上图中,我们把其中Presentation Model部分简称为PM。需要注意的是,Presentation Model对谁来进行操作识别有两种选择,一种是由PM来,PM监听视图事件,然后分析;另一种是由视图自己来,然后把操作识别的结果发给PM。我们没有列出第一种,因为它和MVP差不多。所以,我们把注意力主要放在第二种上。这样的好处就是PM更轻了,PM主要负责业务逻辑部分。说到这里,大家应该知道我为什么选择第二种方式了,这就是我一直想要的:对模型的分解、对业务逻辑部分的职责担当。PM虽然可以作为业务逻辑的入口,可以回答上篇业务逻辑相关的第一个问题:谁,从哪,怎么得到业务请求?,但是,它只负责部分的业务逻辑(主要和视图显示相关),而模型部分负责主要的业务逻辑和外部数据。并且,对应Presentation Model模式来说, PM的初衷并不是作为业务逻辑的facade,而是作为视图的抽象。但是,的确,从形式上,我们看到了一丝希望。

接下来,我们看模型部分:


这里,并没有像MVC或者MVP一样,把模型的改变直接发送给视图,而是给了PM。这样,模型就独立于具体程序,针对不同的场景,定义不同的PM即可。这样真的就可以做到一个Model,多个视图了。

最后,我们看看视图部分:


视图看不见模型,只能看见PMPM可以从模型中获得数据,然后直接抛给外部;也可以在抛之前,对数据进行修改。这获得了极大的灵活性。比如,在MVP中提到的数据类型问题,在这里就迎刃而解。至于视图皮肤状态,PM也能很好的支持。

可以说,Presentation Model比其他模式更靠近我们心目中所想。它提供了三个比较有意义的参考:

1.         场景相关业务逻辑和模型的分离

2.         数据到视图前的转换

3.         视图数据(包括皮肤状态)的统一管理

但是Presentation Model,还是有让人不满意的地方。首先,就像前面说的,它没有积极拥抱业务逻辑,而只是形式上可以作为业务逻辑的入口。其次,操作识别没有和视图分离,导致了视图的复杂性,尤其当操作识别很复杂的时候,可能还需要业务逻辑的支撑,这样PM作为中转站,也会不堪重负。

好了,三个模式已经分析完了,大家可以看到,每一个都有一些问题。基于此,在下一篇,我们将提出自己的模式—反射弧模式。

0 0
原创粉丝点击