类MVP实践报告

类MVP实践报告

为什么要叫(类)MVP呢?因为MVP只是一种设计思想,大概的定义普及后,到了每个人手里都有不同的理解。想想当今的MVC吧,光一个C就能吵成一片,别说M和V的交互了。

下面讲的所有MVP都属于我自己的理解,为不引起定义上的无意义争执,这里用到了“类似MVP”的概念。至少到现在为止,我用的还是很爽的嘛~

克守常规是非常愚蠢的一件事

=====================

目录

1.MVP基本概念
2.MVP的一般模糊点
3.以数据为轴心的架构设计
4.三层之间交互的参数类型
5.MVP缺点

====================

1.MVP基本概念

MVP是基于MVC的演化。解决了MVC模式最大的困扰点:C的混乱。

V:View层,MVP的View层只负责界面的显示,是薄薄的一层,不负责任何业务逻辑。(View你一定要做到很薄很薄吗?)

P:Presenter层,负责业务逻辑处理的一层。对照MVC,可以理解为将原来C中的逻辑代码抽取到P中,View显示代码下方到V中。P负责V和M的交互,V和M不再直接依赖。

M:负责数据的获取和保存。M也是争议较大的一个,我们在下一节中详述。

MVP彻底实现了三层解耦,让整个项目结构非常清晰。其核心目的是实现代码复用与TDD开发模式。

2.MVP的一般模糊点

就像MVC三层的基本概念一直争论不休,MVP的同样存在很多争议点,这里大概讲一下我理解下的MVP

最简单当属V层,所以我们从V开始。

1)V是薄薄的一层?

V的薄,有多薄?难道真的只是几个负责界面布局的XML文件?NO~ !

以Android为例,XML文件负责基本界面的展示,但这是远远不能满足需求的,所以还有Activity这个东西。Activity是Android应用的基本组成模块,可以看做应用每一个页面的载体。在MVC中通常作为C,但是其恶果也很明显,Activity代码通常暴涨到了几千行。

所以Android中的V,其实并不“薄”,它还包括Activity这个比较重量级的东西。Activity负责了View视图的所有任务(复杂控件管理、事件监听)。

当然里面没有任何业务逻辑代码。这才是V的“薄”所在。

2)V只负责视图的展示,不包含任何逻辑?

如果你认为你的V层只有简单的几个setText(),setImage()方法,那可就大错特错了。真正开发起来,你就会发现如此单调的代码根本无法满足业务需求。

你说,所有的逻辑判断代码都扔到P中?哦~我想你是又想看到一个几千行的P层模块了。

逻辑分为两块:业务逻辑 & 视图逻辑。

业务逻辑是指所有实现项目业务功能的代码。

视图逻辑只指View本身的一些现实逻辑,这里比较模糊。举几个例子:判断软键盘是否弹出从而改变View现实,判断ListView是否滑到了底部或顶部,滑动手势监听等等。他们都有一个共同的特点,纯View视图复杂逻辑代码(至于监听到事件的具体处理功能,当然是交给P去做了啊)。

通常项目中有两快是变动最大的:

由设计和产品影响的界面部分。(这个太丑了,改改改!!)

由产品和运营影响的业务部分。(竞对居然上了这么一个功能,不行,我们也要有!改改改!!!)

所以你真的不能把View逻辑和业务逻辑混在一起。越容易变动的东西就越要封装起来,让它在小黑屋自己折腾。

3)P只是负责V和M的交互,是V和M的桥梁,所以里面除了V和M的调用代码,就什么代码都不应该有,P才真是薄薄薄?

哎……我想说,你使用新的架构模式是为了什么?你重构代码是为了什么?A → P(A → M)→ M。这样的一套代码意义何在?

P的职责是承担起多变的业务逻辑,可以不影响V和M的情况下应对多变的产品经理。

P的职责还在于实现TDD(测试驱动开发),虽然你的项目可能并没有这样做,但也应该有这样的潜力。

存在皆合理,物必尽其用。一个薄薄薄的P,存在的合理理由是什么?既然提供了一个P,就应该物尽其用,让它干些力所能及的事情。无用代码是所有开发都不愿意去写的。

4)P应该负责起所有逻辑吗?

P本身负责了V和M的交互,这就是不小的代码量,再负责起所有的业务逻辑,代码量不又是蹭蹭的往上涨?一个超大型的类,谁也不愿意维护啊!!

这里就又要提一个词了:封装!!

一些简单的业务逻辑我们可以直接在P中去写,但是复杂的,你可一定要封装啊。小到字符串的为空判断(因为通常要判断是否等于NULL,和是否等于空字符串),大到一个业务的处理,比如用户数据安全验证。

那你可能就会问啦,这封装起来了,还是算是P层里的内容了嘛?确实不能算了,应该归到M里,这个后面我们马上讲。

所以一个理想的P应该是什么呢?P的内部是一套算法框架,负责任务的调度与分发。而这套算法调度的是什么呢?是V和M的模块。

那么不是又和上面的问题冲突了吗?【 P只是负责V和M的交互,是V和M的桥梁,所以里面除了V和M的调用代码,就什么代码都不应该有,P才真是薄薄薄?

上面讲的问题,P真的只是一个单纯的V – M 调用。具体的算法框架是现在了M中。只是错误的。

5)P层的模块划分应该是怎么样的?

View的划分很简单,一个界面一个View。Model的划分跟着P走,当然还有其他的封装类。那么P应该怎么划分呢?

也是每个页面一个P吗?不~这是非常愚蠢的做法。P的模块划分应该从功能上做。原因有以下几点:

  • 以纪念日模块来说,纪念日的显示和纪念日的修改添加时两个页面。这是一个功能,且这两个是联系非常紧密的界面,这两个页面用两个P,你觉得交互起来还方便吗?

  • 一个功能模块其数据应该是统一管理的,用1个P即可实现数据的统一管理。

  • 你不会愿意看到一大堆只有一个方法的P模块和M模块。

那么你会问了,如果我用一个P的话,岂不是在纪念日显示界面可以调用纪念日修改页面的P方法了?嘿嘿,难道你忘了还有接口这个东西吗?接口就是用来隔离的呀。

6)M到底是什么?
  • M,模型。可不只是单纯的实体类。

  • M负责所有的数据获取和保存操作:网络、Dao等

  • M包含所有的封装类:某某数据处理的封装类。(用户数据验证处理、图片处理、工具类等等)

3.以数据为轴心的架构设计

MVC设计结构是以什么为运转轴心的?是指令。由Controller对View和Model下达指令,通知V和M的变化,然后让他们各自去对方那里拿数据。

而现在V和M已经没有办法直接依赖了,怎么办呢?

以数据为轴心的架构设计

V-P-M三层之间的交互不在通过指令,而是数据。

这里要感谢java的引用机制。从Model层获取的数据,无论传递到哪,数据也只有那一份,其他持有引用的模块对其进行修改,Model的数据都会跟着改变。

V中不在持有数据集的引用,所有数据皆由P层传递直接显示。对数据的处理分发交由P来管理。当V有数据刷新时,P修改自己持有的数据引用,然后告知Model进行刷新。反正亦然。

4.层与层之间交互的参数类型

下面我们讲的是层与层直接交互,传递参数的类型应该是什么才好。

当P要通知V刷新界面时,我们来看下面两种View接口设计

//方案1:刷新View时,直接传递基本数据类型
public interface IMemorialView {

    void updateView(String title,String buildName,String year,String month,String day);

}


//方案2:刷新View时,直接传递一个javaBean
public interface IMemorialView {

    void updateView(MemorialDto memorialDto);

}

按照传统的MVP架构设计,应该采用的是方案1.因为View不需要管你给我什么对象,你给我基本数据类型我显示就好了。如果采用方案2.我还要去解析这个javaBean.我不单纯了呀。

可是这样真的好么?

思考一下,View是多变的,如果有一天我们要显示的不是这几个字段了,换了。那么好吧,你看看你需要改多少地方:View接口,View接口的实现类,调用View接口的类。接口的变动是最痛苦的,软件设计最应该保证的急速接口的稳定。

那么如果采用方案二。只需要改变View接口的实现类就好了呀。

P → V的交互,采用实体类传递。

反过来,当V要传递数据给P的时候怎么办?

这个时候我建议你传递基础数据类型。因为V并不适合实体类的组装(它太薄了,很多必要属性都没有),同样,还有数据安全验证,这是要由P来做的。

V → P的交互,采用基础类型传递。

5.MVP缺点

MVP的优点很明显且诱人,缺点也同样明显且致命。

接口的“过度”使用,在接口有改动时非常痛苦。

MVP首要实现的便是解耦,所以三层交互都是通过接口来实现的。这样的三层接口设计,通常都是牵一发而动全身,三个接口都变。这对开发者来说是极其痛苦的。

这确实是非常棘手且不得不面对的问题。这样的问题,只能依赖于经验丰富的架构设计和解耦设计。

尽量做到接口稳定,和V - P层的解耦关系。

最后说一下关于MVP实现代码复用的问题。

我对这个“代码复用”的理解,并不是说这段代码可以直接拿到别的地方用,而是说,通过V-P解耦,可以实现在V和P有任何一方单独改变时,另一方不需要任何变动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值