什么是MVC
MVC,Model View Controller,是软件架构中最常见的一种框架,实际就是把业务逻辑、数据、界面显示的代码分开组织,各层专注于各自的功能,易于扩展、管理等
在具体开发过程中,MVC就是通过controller的控制去操作model层的数据,并且返回给view层展示,如图
MVC三层之间的关系
Apple是这样说的,在MVC下,所有的对象被归类为一个model,一个view,或一个controller。Model持有数据,View显示与用户交互的界面,而controller调解model和view之间的交互。
- View层
继承自系统视图基类封装的所有自定义View - Model层
针对业务模型,建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作。 - Controller层
安卓的activity,iOS的UIViewController层,用来初始化界面,网络请求展示数据,还要处理view层的交互事件,具体的业务逻辑等
MVC存在什么问题
MVC经典的被用了那么多年,有问题吗?当越来越复杂的业务逻辑需要处理,无数个model view controller,我们需要三者之间进行通信,回调,事件传递,我们发现MVC是有问题的,或者说实现绝对的MVC很难
1、经典存在问题是大部分写MVC的结构都是这样的,model管理数据,Controller中引用model当作属性,Controller中引用view当作属性,view中Import model当作预留属性(这句便是耦合,将M和V建立起了关系),使用时是这样的,Controller来调度View和Model(承载view将Model数据进行展示,Controller中的网络请求来更新Model,同时通过View的Setter方法更新view),这样可以说是V被M给耦合了。这便是经典MVC存在的弊端,但是为什么还有好多人去这么写?是因为快!操作快,这就是伪MVC的经典好处也是存在的耦合弊端。
2、controller的负担随着业务的复杂度持续增高,数据请求,初始化视图,处理业务逻辑,臃肿的controller导致代码不易维护,也增加了测试的复杂度
什么是MVP
MVP作为MVC的演化,解决了MVC不少的缺点,MVP的model层和MVC是一样的,而view和controller都属于view层,所有关于用户事件的转发全部交由presenter层处理。下面还是让我们看图
- 1、View就是MVC的view和controller,在MVP中只负责view层,如controller只负责初始化视图,view展示
- 2、presenter层替代了原来controller层的网络请求,业务逻辑等所有关于用户事件的转发处理
- 3、Controller会持有Presenter,同时持有View,通过presenter获取到model层数据,那View层怎么和presenter通信呢,需要View层定义API,比如刷新资讯推荐列表,刷新banner数据,Persenter在获取到model之后,调用View层的API进行数据展示
- 4、如此一来,Preseter实现了Model和View的完全解耦。代码可复用性高了,维护成本低了,实现了测试驱动开发(调用presenter的方法就能测试,不依赖视图)
- 5、问题:1. 随着业务逻辑的增加,一个页面可能会非常复杂,UI的改变是非常多,会有非常多的case,这样就会造成View的接口会很庞大。
MVP使用案例,伪代码
- View 层
//新闻listView,1 进入时的数据加载动画,2 数据加载完成后展示,隐藏加载动画,3 数据加载失败(网络原因等)要给用户反馈
Class NewsView(){
func showLoadingView();
func showNewsList(newsList[]);
func hideLoadingView();
func refreshLikeStatus(isLike);
func refreshCollectStatus(isCollect);
......
}
- Model 层
// 新闻Model,1 定义新闻字段,2 缓存新闻数据,3 读取新闻缓存数据
Class NewsModel(){
String newsID;
String newsTitle;
String newsIcon;
String newsUrl;
String newsTime;
func cacheNewsList(newsList[newsModel]); // 缓存
func readCacheNews( ) -> Array; //读取缓存
}
- Presenter 层
//Presenter,1 请求新闻数据, 2 调用NewsModel缓存新闻数据, 3 调用View层接口刷新UI 4 处理用户事件
Class Presenter(){
private newsV: NewsView;
private newsM: NewsModel;
func requestNewsData(url,param);
func likeNews(newsModel); //点赞
func shareNews(newsModel); //分享
func collectNews(newsModel); //收藏
}
- Controller 层
//新闻列表控制器,1 初始化视图进行展示 2 初始化presenter进行网络请求
Class NewsController(){
private newsView: NewsView;
private newsPresenter:Presenter
func createView();
func layoutView();
}
MVVM和数据绑定(DataBinding 和 RAC)
MVVM+数据绑定解决了MVP中View层可能会API过多的问题
实际项目中需要事件传递,不同对象间通信,也就是一方的变化需要传达给另一方,传统的实现方式有通知、代理、观察者模式等等,但是这些方法代码分散,不易维护和管理,所以数量不宜过多;数据绑定机制(单向绑定和双向绑定)就解决了这一问题,iOS中有RAC,安卓有DataBinding,前端有VUE
在MVVM中,由于ViewController持有ViewModel,而ViewModel不能反向持有ViewController,所以,当ViewModel中发生变化时,需要通知ViewController,所以需要将ViewModel中的一些内容与ViewController绑定起来,这称为单向绑定;有时ViewController和viewModel中任何一端发生变化,对方都能知道,这称为双向绑定。ViewModel与Model之间的关系同理。