MVP那些事儿 (2) 初探MVC架构

目录

MVP那些事儿(1)……用场景说话ios

MVP那些事儿(2)……MVC架构初探算法

MVP那些事儿(3)……在Android中使用MVC(上)设计模式

MVP那些事儿(4)……在Android中使用MVC(下)缓存

MVP那些事儿(5)……中介者模式与MVP的关系服务器

MVP那些事儿(6)……MVC变身为MVP网络

MVP那些事儿(7)……Repository设计分析架构

为何要先介绍MVC?

若是你要想更佳深入的理解MVP,并在实际开发中灵活的应用,那么就要先了解它的低配版MVC,他俩只是一步之遥,先了解MVC再学习MVP,MVP的优点才能凸显出来,这样连贯性的学习才会加深对MVP的理解。框架

咱们在上一章提到,MVP那些事儿(2) 用场景说话 对咱们的案例进行MVC的设计,也就是第一步,如何实现一个MVC,在实现以前咱们先搞清楚几点概念。异步

MVC的做用?它是设计模式吗?是框架吗?是架构吗?

MVC属于分层架构中的一员,不管是哪个层从复用性和扩展性都是由当前业务所限制的,若是一开始就从复用和扩展上做为出发点来使用MVC的话,必定要有足够的开发经验(并非不能够,分层架构也是能够有扩展性的,但要考虑主次),除非你很是明确将来软件的复杂度。举个例子,好比有一个算法,它处理一组数据所需的时间关系以下:10条,须要1秒,20条须要1.8秒,30条须要2.5秒,,,,100条须要6秒,这个时间复杂度能够看出什么,能够看出这个算法处理的数据量越大,它的处理所消耗的时间递增越缓慢,也就越是大数据量越能体现它的价值,再举一个实际中的例子,人均100的餐厅,两我的去也许每一个人只能尝到2~3种菜样,但四我的去,每一个人会尝到4~6菜样,20我的去,你也许能够把他们家的菜尝个遍,MVC也是如此,软件的复杂度越高,越能体现MVC的扩展价值,这就是我为何要讲不要一上来就想从扩展性做为使用MVC的出发点,除非你是一个颇有经验的人,能提早估计出项目的一个大体的复杂度。更稳妥的方式应该是在项目的推动中不断的优化本身的架构,不少萌新会进入到误区,一看MVP你们都在用,本身设计一个吧,到最后发现根本就你一我的在吃菜,更关键的是别人想和你吃也吃不了,不通用,根本没法体现它的扩展价值,负责人发现后第一反应是,你搞这么多接口抽象类干什么?就你一我的用,搞事情。 布局

MVC不是简单的设计模式

一个只为了分层就能够被叫作设计模式的话,那么外观模式看来还不是最尴尬的模式,因此它不能简单的称呼为设计模式,由于它的范围和深度更加立体,称为架构更为稳当,固然也能够称之为复合设计模式,它里面包含了,策略,组合,观察者,等设计模式。那么,架构和框架的关系又是什么呢?

架构和框架说的不是一回事儿

MVC是一种架构思想,而基于这个思想的框架也叫MVC框架,在ios的开发中,系统为咱们实现了公共的视图类UIView,和控制器类UIViewController,还有大名鼎鼎的Struts2框架,都是基于MVC架构设计出来的框架(基于MVVM架构的DataBinding,Architecture Components框架),框架是一个有边界的可扩展集,它在可扩展的同时也是有边界的,也就是说你只能在这个框架里玩耍,而没法超出这个框框。若是你只是在项目中使用了MVC的思想去作分层,那么这个项目或模块用的就是MVC架构设计,若是你用了Struts框架,那么这个项目使用了MVC框架。当你向别人介绍你的项目时,你能够这么说:个人项目使用的是MVVM架构,具体用到了Architecture Components做为框架来进行开发,千万不要说成:你们好,我来介绍一款基于MVVM框架设计的Architecture Components架构,这听的得多别扭啊。

一句话总结——架构是蓝图,而框架是实实在在的产品,MVP架构就一个,而基于MVP架构设计的框架能够是千千万万个。

以上就是对MVC的一个大体的介绍,学习MVC以前,要先会写,学会了写,再学习用,接下来咱们先实现一个MVC框架。

实现MVC什么?MVC(框架)

在第一章的场景里咱们挑一个需求,咱们来实现一个向服务端请求数据,并显示在列表的需求。

需求时序图
在Android中咱们实现上面的需求,一般状况是在界面的Create时,调用一个请求接口,经过异步的方式返回数据,待数据返回时更新UI,咱们用一个Activity来实现:

public class TasksActivity extends AppCompatActivity {
    protected void onCreate(Bundle savedInstanceState) {
        //...初始化
        //请求列表数据
        Data data = loadData();
    }
    void onDataCallBack (Data data) {
        //更新列表
        upDateList(data);
    }
}
复制代码

这是一段简单的示例代码,一般状况下咱们用像loadData这样的方法去请求数据,而且绑定监听,监听数据的返回,当数据返回时,像onDataCallBack这样的回调方法会被触发,同时进行ui的更新。

一样的需求,用MVC写一遍

MVC分别为Model,View,Controller,顾名思义,首先咱们须要建立这三个对象,第二步,咱们把这三个对象组合起来,咱们先一个一个的认识它们,逐个击破,首先从简单的来,Model,

什么是Model,它的职责

逻辑层(领域层)Domain Object,逻辑执行体,除此以外也能够兼顾JavaBean的职责,但Model层可不是简单的Value Object。而 JavaBean也就是Value Object,只是用来封装数据,不具有Model层的职责,固然也能够把JavaBean看成Model类的一个内部类来使用,固然也能够单独一个类,一般咱们也会这么做,方便复用。 萌新⚠️

一、JavaBean不是Model,但Model也能够包含JavaBean的职责,但不是必须的。 二、Model是用来处理数据的,如获取数据(本地或者服务端),数据处理,如CURD。

按照上面的定义咱们来写一个Model

/**我是一个Model**/
public class TasksRepository {
    //从服务器请求获取数据
    void getTasks() {}
    //从内存缓存获取数据
    Data getTaskCache() {}
    //从磁盘缓存获取数据
    Data getTaskDiskCache(){}
    //保存一条数据
    boolean saveTask(Task task) {}
    //对数据进行排序
    Data orderData(Data data, int orderType){}
}
复制代码

首先咱们建立一个Model类名为TasksRepository,首先不要关内心面的Data和Task对象,它们只是普通的Bean对象,TasksRepository里面包含了五个方法,按照以前的定义,它是有获取数据的职责的,因此这其中三个方法都是和获取数据相关,好比getTasks,你能够调用网络组件进行数据的获取,它还能够对数据进行CURD的操做,好比savaTask的方法用来保存一条数据,还能够对数据进行业务处理,好比用orderData方法对数据进行从新的排序。

一句话总结,Model负责获取数据,操做数据,和对数据进行业务处理。

什么是View,它的职责

接下来咱们讲一讲View,View就是咱们的视图层。

一、它的主要职责为呈现Model的数据、主动询问状态或被动的监听 二、通知控制器Controller去处理一些事情 三、接收Controller,编辑本身与Model无关的状态

按照View的职责咱们来设计一下这个类

/**我是一个View**/
public class TaskView {
    //当列表初始化后,告诉控制器该加载数据了
    void viewCreate() {
        controller.loadNomData();
    }
    //更新列表
    void upDateList() {
        //主动请求Model获取数据
        Data data = tasksRepository.getTaskCache();
        //更新ui
        list.update(data);
    }
    
    void beginLoadData(){
        list.showHead();
    }
}
复制代码

在TaskView中也就是咱们的视图对象,它包含了俩个对象,分别为controller和taskeRepository,controller就是控制器对象,咱们下一个讲它,taskeRepository就是咱们的模型,上面提到过它,先不要关心这两个对象是怎么初始化来的,要关心的是View视图对象是包含了C和M的,按照职责它必须这么作,首先像viewCreate这类方法通常是在界面初始化时调用的(在Android 中多是Activity或者Fragment初始化时调用的,也多是某一个执行动做),让controller去执行loadNomData的方法请求数据,这里惟一须要注意的是,并无明确的告诉controller请求的数据是从什么地方来的,也许是缓存,也许是网络请求,view是无需关心这一点的。同时还要注意的是,在讲解Model的时候已经明确了Model是有获取数据的职责,可是在上面的示例中,**为何是controller去负责获取数据,而不是用Model?也就是咱们的tasksRepository对象?**请你们记住这个疑问,会在讲解Controller时回答。

第二个方法upDataList方法,

//更新列表
void upDateList() {
    //主动请求Model获取数据
    Data data = tasksRepository.getTaskCache();
   //更新ui
    list.update(data);
}
复制代码

它的内部是经过tasksRepository对象的getTaskCache()方法获取数据,这个方法在Model的定义里面,你们还有印象吧。讲到这里,**你们可能发现有一个严重的漏洞,view在执行tasksRepository.getTaskCache()时,是怎么知道这个数据已经准备好了呢?**看view的职责1:

主动的问询或者监听Model

咱们把调用tasksRepository.getTaskCache()看做为主动的问询,而在主动问询前,View应该获得一个有效的通知,这个通知应该由Model发起,当监听到Model:个人数据准备好了,你来拿吧时,View会去主动的向Model获取数据。举个现实中的例子,你在网上买东西,如今通常都往快递柜里投放,等到短信通知你快递到了时,你才会去快递柜里拿商品,但也许你实在等不及了,也能够每天打电话,咱们就不详细讨论了,View和Model但关系也就是观察者与被观察者的关系。但是,在上面的示例中咱们没有写出监听Model的代码,请你们记住这个疑问,我会在后面讲解三者的依赖绑定时会揭晓答案。 最后一个方法,beginLoadData(),

void beginLoadData(){
        list.showHead();
}
复制代码

当开始请求数据时,list会显示本身的头布局,像beginLoadData这样编辑view自己的方法在实际开发过程当中还有不少,它们关注的是控件自己的状态,最重要的,这样的方法可能会被Controller随时的调用,咱们在讲解Controller时进行讲解。

什么是Controller,它的职责

Controller,也就是咱们的控制器,它把视图的操做发送到模型。

接收View的操做,并转调给Model 改变View的状态

按照上面的职责,咱们尝试的设计一下这个类:

/**我是一个Contorller**/
public class TasksController {
    
    void loadNomData() {
        if(tasksRepository.getTaskCache() == null){
            //执行Modle
            tasksRepository.getTasks();
            //执行View
            view.beginLoadData();
        }
    }
}
复制代码

在对Controller讲解以前,咱们先停顿一下,在以前的介绍中咱们好像遗留了几个问题,在介绍View时,我用加租文字的方式标示了三个问题,在介绍Controller时咱们将要解决掉问题1,和问题3。咱们一块儿回顾一下这2个问题:

疑问1,在讲解Model的时候已经明确了Model是有获取数据的职责,可是在上面的示例中,为何是controller.loadNomData()去负责获取数据,而不是用Model?也就是咱们的tasksRepository对象?

这个问题要从Contrller的职责提及:接收view的操做,并转调给Modle。什么是view的操做,好比list的下拉刷新操做,转调给Model,也就是说其实Controller并无实际的实现加载数据的代码,而是让Model去执行,解释完之后,看一下TasksController里的第一个方法loadNomData(),

void loadNomData() {
        if(tasksRepository.getTaskCache() == null){
            //执行Modle
            tasksRepository.getTasks();
            //执行View
            view.beginLoadData();
        }
    }
复制代码

它内部第一条语句:

tasksRepository.getTasks();
复制代码

而tasksRepositor对象就是咱们的Model,它执行了getTasks()的操做,其实controller的loadNomData()方法只是对这个过程进行了一个封装。听完上面的解释,咱们知道Controller是这么设计的,但是又一个问题出现了,虽然咱们知道了Controller转调了Model的方法,但是我为何要这么作?我直接在View里调用tasksRepository.getTasks();不能够吗? 清你们记住这个问题,我下一章为你们解答,咱们先学会写,再去研究怎么用。

疑问2,像beginLoadData这样编辑View自己状态的方法在实际开发过程当中还有不少,它们纯粹关注的是控件自己的状态,最重要的,这样的方法可能会被Controller随时的调用。

咱们先回顾一下这个方法beginLoadData()

//controller会随时调用
void beginLoadData(){
        //显示列表的头部,改变了列表的属性
        list.showHead();
}
复制代码

咱们仍是从Controller的职责来讲,Controller有权利对View的状态进行改变,无论是通知的形式,仍是直接的访问。并且View的职责里也说明了,它是能够接收Controller更改本身的状态,而更关键的一点这个状态的改变是无需依赖Model的,更加的纯粹。

有了上面问题的承上启下,咱们再回头看一下TasksController里的loadNomData()方法,它首先判断了是否能够从tasksRepository里拿到缓存,若是没有就执行getTasks(),同时通知view我要开始加载数据了,view会在beginLoadData()方法中对本身的列表控件进行一个显示头部的处理,至关规范的一个封装。

**总结:**到此,咱们已经学习完了MVC这三个层的定义和职责。在文章的开头我有讲过,要想用MVP,就要先用MVC,要想用MVC就要先会"写"MVC,写才是第一步,咱们首先把MVC这三个层,拆分红三个片断,每个片断都规范好它们的职责,而后咱们再想办法把它在组装在一块儿,在下一章咱们要解决如下问题:

一、如何把这三个片断组装起来?在Android里怎么写? 二、view在执行tasksRepository.getTaskCache()时,是怎么知道tasksRepository数据已经准备好了呢?怎么通知view的?

MVP那些事儿(3)……在Android中使用MVC(上)

谢谢你们关注和评论,更新的有些慢,不如关注我一下,随时知道更新进度。

相关文章
相关标签/搜索