内容简介:以前本人一直用的都是MVC的设计模式去开发应用的。封装MVC的基类等等,和一些工具类配合开发。甚至去过的公司也都是这种方式,就连苹果的基类名字都是以View,Controller(UIView,UIViewController等)结尾的。但是这次发现公司controller层代码量异常的庞大(想找个方法,滑动半天都找不到,好累...,主要是写法不规范,冗余代码太多),虽然重构了基类,从而减重了controller类,但是发现还是过于冗杂。公司的网络请求一个界面有多个,导致一个controller有好多网络请
以前本人一直用的都是MVC的 设计模式 去开发应用的。封装MVC的基类等等,和一些 工具 类配合开发。甚至去过的公司也都是这种方式,就连苹果的基类名字都是以View,Controller(UIView,UIViewController等)结尾的。但是这次发现公司controller层代码量异常的庞大(想找个方法,滑动半天都找不到,好累...,主要是写法不规范,冗余代码太多),虽然重构了基类,从而减重了controller类,但是发现还是过于冗杂。公司的网络请求一个界面有多个,导致一个controller有好多网络请求的代码。之后尝试用mvp设计模式去重构发现好多了,层次分明了,世界清净了哈哈。
那是不是iOS开发只能用MVC的设计模式呢,显然不是的。MVC,MVP,MVVM(统称MVX系列)其实都可以的。其实android现在普遍在用MVP的设计模式,前端(vue等)都在用MVVM的设计模式。
有这么多的设计模式,iOS开发应该选用哪种设计模式呢,哪种更好呢,带着这些问题我们去探索一下这些设计模式在iOS开发上的应用,特点,以及他们不同。看看哪种设计模式更适合自己。
MVC
M:Model,它是模型类,就是有很多属性,每个属性名字和后台返回的字段名相同。
V:View,它是视图类,如继承与UIView类的所有类都可以认为是V层。这个类里存放的都是和视图相关的逻辑代码。
C:Controller,它是控制器类,这里是主要写各种逻辑的地方,这里控制着M层数据源,控制着View的展示等等。
三者关系是,c层持有m层,持有v层
可见C层控制着view的展示,控制着M数据的填充,一些点击事件一些逻辑,甚至网络请求代码等等。这使得C层异常的庞大。为了解决这个问题,我们引入了各种工具类,甚至封装各种基类试图用这些工具类封装的代码去减轻controller。但是事实表明这样做还是不能对controller彻底瘦身,controller层还是庞大。
还有个问题是层次并不是那么的分明,比如controller层是视图控制器,那就控制视图好了嘛,干嘛要负责那么多任务呢。既要负责网络的请求,又要负责各种数据层的逻辑,这有些违反了视图控制器的这个概念。
可见传统的MVC设计模式有着不可避免的两大问题,controller庞大,层次不明。为了解决这个问题,从而引出了MVP的设计模式
MVP
M:Model,它是模型类,就是有很多属性,每个属性名字和后台返回的字段名相同。
V:View,它是视图类,如继承与UIView类的所有类都可以认为是V层,并且Controller也属于V层,即继承与UIView,UIViewController类的所有类都属于V层。这个类里存放的都是和视图相关的逻辑代码。并且controller类里存放的是一些胶水代码(就是起到粘合作用的代码)。
P:Presenter,它是P层,这里是主要写网络请求,数据逻辑的地方。处理和视图无关的数据逻辑等。这个类不该持有v层,也就是不该#import <UIKit/UIKit.h>
三者关系是,v层持有p层,p层持有m层,并回调给v层。
从上面介绍可以看出,MVC中的C层中的网络请求,数据逻辑代码被移动到了MVP中的P层中。这样做一是可以减轻MVC中的C层的代码量,又可以使得层次分明。
下边我们用一些伪代码来进一步探索MVP的应用,其实和MVC一样,我们也需要封装出一套MVP的基类。用这些基类可以使得我们编码更方便。
//MyModel类 #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface MyModel : NSObject /** 头像 */ @property (copy, nonatomic) NSString *img; /** 昵称 */ @property (copy, nonatomic) NSString *nickName; @end NS_ASSUME_NONNULL_END //MyVC类 #import "MyVC.h" #import "MyPresenter.h" @interface MyVC () @property (strong, nonatomic) MyPresenter *presenter; @end @implementation MyVC - (void)viewDidLoad { [super viewDidLoad]; //持有P层 self.presenter = [[MyPresenter alloc] init]; [self setUpUI]; //网络请求 [self fetchData]; } - (void)setUpUI{ //布局代码... } - (void)fetchData{ [self.presenter fetchData:^(MyModel * _Nonnull model, NSError * _Nonnull error) { if (error) { //出错处理 }else{ //数据赋值 } }]; } @end //MyPresenter类 #import "MyPresenter.h" #import "MyModel.h" #import <BSUtilsBaseRequestManager.h> @implementation MyPresenter - (void)fetchData:(void(^)(MyModel *model, NSError * _Nonnull error))finishBlk{ [[BSUtilsBaseRequestManager new] postWithUrl:@"xxx" parmas:@{} finishBlk:^(NSDictionary * _Nonnull responseObject, NSError * _Nonnull error) { //json转model //数据整理,数据逻辑 if (finishBlk) { finishBlk(model,error); } }]; } @end 复制代码
总结
通过比较分析可知,传统MVC,C层代码量庞大,层次不分明。MVP设计模式把网络请求,数据层逻辑抽出来放到P层,这样解决了C层代码量庞大问题,也解决了层次分明问题。
其实采用mvp设计模式后不仅仅解决了c层庞大问题,层次分明问题。而且p层是复用的,比如我们一个地方用到了点赞功能,我们就可以持有点赞功能的p层去调用相应的点赞方法即可。如果是用传统的mvc设计模式,网络请求都是写在了c层,我们每次都得复制粘贴点赞的请求方法,异常的麻烦,如果想复用这段代码,就要考虑写成类方法,并且要考虑耦合性问题,还是比较麻烦的。但是用mvp后所有的网络请求的p层相当于都是复用的了,随时都可以无耦合的调用。
当你用了mvp设计模式后可能有时会发现p层代码量很少,但是却独占一个类,这时候可以考虑p层合并。比如我们有两个界面,一个界面是一级分类,另一个界面是二级分类。这时候两个界面我们可以考虑用一个p层,两个界面的网络请求代码都放到一个层中。但是有时候是无法合并的,因为这个p层和其他p层没有相同的含义,这时候硬是合并是不合理的。这时候确实会存在一个p层就一个网络请求的方法但是却独占一个类,这是没有办法的。但是这样也确实是层次分明了,这个网络请求代码可以复用了,有利也有弊吧。但是我觉得利是大于弊的,比起mvc我还是比较喜欢用mvp的设计模式。
以上所述就是小编给大家介绍的《从MVC到MVP》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据驱动:从方法到实践
桑文锋 / 电子工业出版社 / 2018-3 / 49
本书是从理论到实践的全面且细致的企业数据驱动指南,从作者的百度大数据工作说起,完整还原其从零到一构建百度用户行为大数据处理平台经历。详解大数据本质、理念与现状,围绕数据驱动四环节——采集、建模、分析、指标,深入浅出地讲述企业如何将数据驱动方案落地,并指出数据驱动的价值在于“数据驱动决策”、“数据驱动产品智能”。最后通过互联网金融、电子商务、企业服务、零售四大行业实践,从需求梳理、事件指标设计、数据......一起来看看 《数据驱动:从方法到实践》 这本书的介绍吧!