论MVVM伪框架结构和MVC中M的贯彻机制

By admin in 亚洲必赢app在哪下载 on 2018年9月13日

目录

  • MVC概论【本文】
  • 模型层设计方式【请参见:http://www.jianshu.com/p/fce02188edec】
  • 控制层的宏图方【敬请期待】

直还有人做吹捧MVVM应用开发框架,文章将MVVM说之动听并且批评包括iOS和android所用底MVC经典框架。这首文章就是是想念给那些捧臭脚的众人泼泼冷水,虽然发生或造成骂声一切开,但是目的是为那些刚入门的同伙一些参考和建议,以免误入歧途。同时为受那些深陷其中不能自拔的伴儿们敲敲警钟,以免其在错的道路及越走越远。

—— MVVM并非框架,而只是简短的公文夹分类 ——

MVVM被引入的前因后果

约莫是当2010年左右平移端支付火了起,起初是iOS,Android,
WinPhone三独好平台竞争,后来膝下退出了斗争,变成了第二分开天下。从以系统布局以及为开发者提供的框架体系来拘禁,两只平台还是产了经典MVC三层结构的开发方式,这三交汇所代表的义是范、视图、控制。这个开框架的初衷其实也很简单:视图负责展示以及渲染,模型负责作业逻辑的兑现,控制负责调度视图的轩然大波以及业务逻辑的调用以及通知视图的刷新通知。
三有松散耦合,各司其职。下面是藏的MVC框架结构:

[图形上传失败…(image-1d68cb-1512992093070)]

一个百般可惜的实是随便是Android和iOS都仅仅针对C和V两有些开展了正规化的概念及促成:Android的视图部分的实现是概念了各种控件以及经XML文件来组装视图布局界面,iOS的视图的实现吗是概念了各种控件以及经XIB或SB来组装视图布局界面;
Android的控制部分则是由此Activity来促成,而iOS的支配部分则是经过UIViewController来实现的。而模型有为?因为每个应用的工作逻辑和下场景并不相同,所以个别单阳台为束手无策也非可知定义来一个通用的模型层出来,而是将模型层的概念留给了开发者来兑现。然而当下吗咱的开发者在行使MVC框架开发使时盖下了隐患。

前期的应用开发相对简单,因为没正式的模型层的概念,而控制层又在工程变更时蓄了不少而供应开发者写代码的地方,所以多开发人员就自然而然的用业务逻辑、网络要、数据库操作、报文拼装和剖析等等全部代码都放入了控制层里面去矣,根本就无欲什么模型层的概念。
这样随着时光的推和应用之错综复杂增加,就起了C层膨胀的图景了。一个控制器的代码可能出现了好几千推行的景象。于是乎有人便开搜索解决方案来吗C层瘦身了。又一个那个惋惜的事实是还尚未丁去思在抽象出M层,而是用了之类方法来解决问题:

  • 客户端和服务器之间交互的多寡报文是否可定义来一个个只有属性而尚未法的数对象啊?这样于拍卖和渲染界面时虽不需要与旧之XML或者JSON或者其它的格式报文交互了,只要操作数据对象就是吓了。于是解决方案就是基于客户端和服务器之间交互报文定义来一个个之数据模型,然后又支付有一致模仿XML或者JSON和数据模型之间互转的解析器来。最后用及时一个个不过出数据如果没办法的对象数据模型统一置于一个地方,然后让他俩定义也M模型层(呼!终于给出模型层的概念了,但是:Are
    you kidding
    me??)
    。这样C层就非会见重复冒出XML或JSON解析和一直读取报文的代码了!而是把当下部分代码挪至范层了(大家来拘禁什么,我毕竟用及了MVC框架了!)
    好了!瘦身第一步成功。但是可,问题还在什么,我之事情逻辑还是一如既往大片在C层啊,看来MVC这种框架为只是这样啊!根本没有缓解自身的题材。不行,我非克还就此MVC这种框架来支付自己之运用了,我只要另找她套,要持续指向C层瘦身。

  • 自我的某某界面和某业务逻辑是绑定在平片的,这个界面的显示是经调用某个业务逻辑来促成的,业务逻辑完成后如直接更新是界面。这种严谨的调用和翻新关系从来就是无欲C层的涉企。因此可以立刻有的界面的翻新刷新以及作业逻辑的调用绑定在合,
    二者结合也一个查封而单身的整并形成独立的接近。这样把这个看似的代码抽离出来了,存放到一个独门的文书夹着。我管这有些让什么好也?对了即为视图模型层VM吧!视图模型层中之类定义了一个于外部使用的唯一接口来供C层调用。这样自己算把同坏组成部分代码从C层中抽离出来了。我曾经成之兑现了C层的尤为瘦身,并抽象出了一个视图模型层了!(不过哪里好像不对,视图模型层设计及了视图、模型、视图模型层三点的交互和耦合)
    不过没有涉嫌,反正我之C层进一步瘦身成功了!,我看还可免得以连续瘦身C层?

V和VM以及M之间的赖关系

  • 本人之许多视图的波是以C层中拍卖的,那自己是不是可将C层的事件处理也拿出去也?
    干脆就以出来吧。但是怎么将出去呢?于是乎我以休鸣金收兵的寻找,终于找到一个叫RAC的物了,这个东西好什么,他好背处理视图的各种风波,以及可以承担连续的网络调用。等等。。。
    RAC就是出接触晦涩难知晓!难以学习,代码难以阅读与调节。怎么处置?
    没有关系,只要是力所能及将C层的代码瘦身这些又到底什么。。。大莫了就算是多和一点坑,多将几潮培训就哼了。
    嗯! 就这么办,那我拿立即一部分代码也放入到VM层里面去吧。

    。。。。呼!!!
    C层终于瘦身成功。然后大家看什么,我之C层里面确实是什么代码也未尝了。。。
    它不再处理视图的波了,因为事件让RAC给处理了、它吧非处理视图的基础代谢和事情逻辑的调用了因吃视图模型MV给处理掉了、他为无处理多少的解析了盖受范层为替换掉了。嗯。。。。我而给这种无C层或者不待C层的框架起个名,叫什么好呢?
    就给:MVVM吧。。。
    我的使可绝不C层了,然后我就奔走相告。将C层无用大白于天下。。

真的是这样吗?答案是NO!!!

先是我怀念说的凡一个大好之框架中列层次的拆分并无是简单的以代码进行归类和分叉,**层次的分是横向的,而模块的剪切则是纵向的
** 。
这其中提到到了层次中的耦合性和职责的剪切,以及层和层中的互动接口定义和措施,同时层内的筹划也相应有着惊人的内聚性和结构性。而这些计划之渴求并无于所谓的MVVM中反映出来。

  • 首先使正确的知MVC中的M是什么?他是数据模型吗?答案是NO。他的科学定义是业务模型。也不怕是公有所事情数据以及业务实现逻辑都应有定义在M层里面,而且工作逻辑的落实同概念应该跟切实的界面无关,也尽管是与视图以及控制中从未外的涉嫌,它是可以独自存在的,您还是足以用事情模型单独编译出一个静态库来提供被第三着或其他系统运用。在点经典MVC图中为老清晰的描述了立一点:**
    控制负责调用模型,而模型则将处理结果发送通知被控制,控制再通报视图刷新。因此我们无可知拿M简单的明亮为一个个单调的只有属性而尚未章程的数据模型。其实这间涉及到一个极端核心的筹划条件,那便是面向对象的核心计划标准:就是呀是相仿?类应该是一个个具备相同操作和不同性质之靶子的虚幻。
    我眷恋今天别一个系里面都不曾出现过一样堆积只发生数据如果没办法的数据模型的汇被定义也一个独立而肤浅的范层来供大家使用吧。**
    我们不能够管一个封存数据模型的公文夹来作一个交汇,这并无入横向切分的平整。所以说MVVM里面的所谓对M层的定义就是是一个伪概念。

  • 上面我已经证实M层是业务模型层而无数据模型层,业务模型层应该封装所有的工作逻辑的兑现,并且与现实性视图无关。我们不能够将一个视图的表现逻辑绑死在一个事务处理逻辑之中,因为生或有一个政工逻辑来多种不同的变现形式,也或界面显得会趁着以升级要转变,但是工作逻辑是对立稳定的。即使是某视图确实就同这个工作是紧密耦合的,也未应该举行强耦合绑定。所以地方所谓的VM这种以视图的示及事务的处理逻辑绑定在同等片是深坏的计,因为如此的筹划方式就全背离了系里头太核心的亮以及促成该分别处理标准。而且这种规划之思量是与分支的见是违反的。因为他出现了视图和工作的紧耦合和互双向依赖问题,以及同所谓的M层也使紧耦合的有。所以说MVVM里面所谓的VM层的定义为是一个伪概念。所谓的VM层这个中只不过是据页面进行的意义拆分而已,根本就是叙不达到所谓的叠的定义。

  • 双重来说说事件处理。经典的C层设计的目的是承担事件处理和调度,不论是按钮点击还是UITableview的delegate以及ListView的Adapter都太好放在C层来拍卖,这也是副C层最实质的概念:就是C层是一个背调度和操纵的模块,它是V层和M层的粘合剂,他的企图就是拍卖视图的事件,然后调用业务逻辑,然后接受工作逻辑的处理结果通知,然后再度通知视图去刷新界面,这就算是C层存在的意义。而且系统默认为是以此法设计之。而RAC的出现则用即刻有些之拍卖给的的代表掉了。也就算是透过RAC所谓的响应式和触发式这种机制就算会落实以事件之调度处理在另地方其他时候还能做到。这样做的目的使得我们可以分流和解说代码。但结果出现的题目呢?就是与一个单元调度处理逻辑与效力的构建完全在了一个地方,但不同的单元逻辑的以散在不同的地方,无法去分类统一保管与保障。因此若无法一下子虽掌握某个功能有调度到底是怎么促成与以何实现之。因为RAC将功能构建和事件处理完全粘合到一个怪之函数体内部,并且是代码套代码的模式,这种措施严重的毁伤了面向对象里面的构建与处理分离的设计模式理论。更麻烦的凡彼高昂的读书与护卫本,代码阅读理解困难,以及无处不在的闭包使用。试想一下是于一个初大家的话是匪是噩梦?,一旦出了问题对于维护和代码调试是勿是噩梦?而且使用不当就会起循环引用的要紧问题。这样一来原本C层一个调度总管的任务被RAC来接管后,这些处理将移得分散和无序,当我们只要开有合的保管仍HOOK和AOP方面的东西常常即换得力不从心下手了。
    不可否认的凡RAC在处理连续调用以及各个响应方面出必然之优势。一个例是咱们或有连接的多个和服务器的网要,这时候用RAC进行这种拍卖能便宜的化解问题。但是自思念说的凡当在这种景象时,我们更是应该拿这种连的大网调用在M层内部消化掉,而仅于C层提供一个简短而惠及之接口,让C层向无需要关注这种调用的连续性。因此得以说为把C层的代码给消化掉而引入RAC的体制,不仅没有简化掉系统反而降低了系的可维护性和可读性。RAC机制向就是不切合用当事件处理中。良好之下和框架并无以代码的多少,而是完全系统的代码简单好读,各部分任务分明,容易保障的调剂

—— MVVM被引入的根本原因是针对M层的错误认识所引起的 ——

MVC中M层实现的守则

说了那基本上,可以总结发生所谓的MVVM其实并无是一样种植所谓的框架或模式,他只有是一个伪框架而已,他只是以作用及拍卖按文件夹的方式进行了分,最终之之结果是网乱成了平锅子粥。毫无层次可言,所负有的绝无仅有亮点是拿C层的代码和效益完全弱化了。其实出现这种设计艺术极其根本之原委就没针对M层进行正确的知晓定义及拆分。那么我们理应怎么样科学的来定义跟规划M层呢?下面是自身个人觉得的几乎独准则(也许跟其他人的视角发生出入):

  • 概念的M层中之代码应该跟V层和C层完全无关的,也尽管是M层的目标是未欲借助任何C层和V层的靶子要独自存在的。整个框架的计划性极端完美结构是V层不依赖C层而独在,M层不依赖C层和V层独立有,C层负责涉二啊,V层只负责展示,M层持有数量以及事务的切实可行落实,而C层则处理事件响应与工作的调用以及通报界面更新。三者之间必然要是明显的概念也就为据,而休应有出现双向依赖。下面是三叠的依靠关系图:

老三重合里的无非为据关系

除非当您系统规划的例外部分都是独自为依靠时,才可能好之进展层次拆分和每个层的机能独立替换。

  • M层要成功对业务逻辑实现之卷入,一般工作逻辑最多的是干到客户端和服务器之间的事体交互。M层里面要做到对运用的网络协议(HTTP,
    TCP,其他)、和服务器之间交互的数目格式(XML,
    JSON,其他)、本地缓存和数据库存储(COREDATA,
    SQLITE,其他)等所有业务细节的包装,而且这些东西都未能够暴露被C层。所有供C层调用的且是M层里面一个个工作类似所提供的分子方法来兑现。也就是说C层是免需知道为无应明白和客户端以及服务器通信所下的其他协议,以及数额报文格式,以及存储方面的情。这样的益处是客户端和服务器之间的通信协议,数据格式,以及当地存储的改观还无见面潜移默化其它的以整体框架,因为提供给C层的接口不换,只需要提升跟换代M层的代码就足以了。比如说我们纪念用网络要求库从ASI换成AFN就设在M层变化就是可以了,整个C层和V层的代码不转移。下面是M层内部层次的定义图:

M层内部的包层次

  • 既然我们的采取是一个完而又细分模块,那么业务层内部也该仍功能模块进行组织划分,而休应有简单且平面的按照和服务器之间通信的接口来开展业务层次的面封装。我相信来很多丁犹是指向M层的卷入就是简的按和服务器之间的竞相接口来概括的包装。下面的有数种植不同之M层实现的工作封装方式:

有限种植不同的M层封装实现

我们还可以更的对准事情逻辑抽象出M层的接口及落实两片,这样的一个益处是同之接口可以产生两样的实现方式,以及M层可以隐藏非常多的里数据以及章程而不暴露被调用者知道。通过接口及兑现分离我们还得当无转移原来实现的功底及,重新重构业务有的兑现,同时这种模式呢殊轻MOCK一个测试实现,这样以展开调试时好很简单的当真正实现与MOCK实现中切换,而不用每次都同服务器端进行交互调试,从而实现客户端和服务器之间的分别支付及调节。下面是一个晋级版本的M层体系布局:

根据接口的M层实现

  • M层如何与C层交互的题材吗需考虑,因为M层是休待明白C层和V层的留存的,那么M层在业务处理完后怎么错过通知C层呢?方法来甚多种:
    • 我们可以吗M层的通知逻辑定义Delegate协议,然后叫C层去落实这些协议,然后M层提供一个delegate属性来赋值处理工作通知的靶子。
    • 咱们为得以定义众多底NSNotification或者波总线,然后当M层的业务处理完后得以发送通知,并且以C层实现通的处理逻辑。
    • 咱得用闭包回调或者接口匿名实现目标的款型来促成工作逻辑完成的关照功能。而且可以定义有正式:所有M层对象的不二法门的终极一个参数都是一个规范的如下格式的block或者接口回调:

typedef void (^UICallback)(id obj, NSError * error);

这种模式其实当众多系统被出应用到。大家好参数考苹果之CoreLocation.framework中之地理位置反解析的类CLGeocoder的定义。还有一些之是于AFN以及ASI中的大网要部分都是把成功和破产的处理分成了2独block回调,但是此地建议于叫C层的异步通知回调里面未分2只block来调用,而是一个block用2个参数来缓解。因为发或我们的处理着无成还是失败都可能来一部分代码是形似的,如果分别则会面世又代码的题目。

MVC中M层实现的大概举例

末了我们盖一个略的用户体系之报到系统来兑现一个M层。

1.概念标准的M层异步回调接口:

//定义标准的C层回调block。这里面的obj会根据不同对象的方法的返回而有差异。
typedef void (^UICallback)(id obj, NSError * error);

//这里定义标准的数据解析block,这个block供M层内部解析用,不对外暴露
typedef id (^DataParse)(id retData, NSError * error);

2.概念有M层业务类的基类,这样在通用基类里面我们好开多处理。比如网络层的联结调用,加解密,压缩解压缩,我们还足以做AOP和HOOK方面的拍卖。

     @interface  ModelBase

           //定义一个停止请求的方法
           -(void) stopRequest;
           /**
             *定义一个网络请求的唯一入口方法
             * url 请求的URL
             * inParam: 入参
             * outParse: 返回数据解析block,由派生类实现
             * callback: C层通知block
             */
           -(void) startRequest:(NSString*)url  inParam:(id)inParam outParse:(DataParse)outParse  callback:(UICallback)callback;
     @end

3.概念一个用户类:

    @interface  ModelUser:ModelBase

        @property(readonly) BOOL isLogin;
        @property(readonly) NSString *name;

       //定义登录方法,注意这个登录方法的实现内部可能会连续做N个网络请求,但是我们要求都在login方法内部处理,而不暴露给C层。
       -(void)login:(NSString*)name  password:(NSString*)password   callback:(UICallback)callback;
        //定义退出登录方法
       -(void)logout:(UICallback)callback;
    @end

4.概念一个M层总体系统类(可选),这个近乎可以是单例对象:

    @interface ModelSystem:ModelBase

     +(ModelSystem*)sharedInstance;

    //聚合用户对象,注意这里是readonly的,也就是C层是不能直接修改用户对象,这样保证了安全,也表明了C层对用户对象的使用权限。
    @property(readonly)  ModelUser *user;  

    //定义其他聚合的模块

    @end

5.每当C层调用用户登录:

  @implementation LoginViewController

    -(IBAction)handleLogin:(UIButton*)sender
   {
        sender.userInteractionEnabled = NO;
        __weak LoginViewController  *weakSelf = self;
       [[ModelSystem sharedInstance].user  login:@"aaa" password:@"bbb"  callback:^(ModelUser *user, NSError *error){

        if (weakSelf == nil)
               return;
       sender.userInteractionEnabled = YES;
       if (error == nil)
       {
              //登录成功,页面跳转
       }
       else
      {
            //显示error的错误信息。。
      }}];

   }

   @end

可以看地方的C层的一对非常简单明了,代码也易读和易于掌握。同时我们还看到了C层跟本不需掌握M层的报到实现到底是什么告网络的,以及告了几乎单网操作,以及用之哎协议,以及什么数据报文格式,所有的立刻周还封闭装于了M层内部贯彻了。C层所设做的饶是粗略的调用M层所提供的办法,然后在callback中通界面更新即可。整个C层的逻辑吗便是几十实行就能打出定了。

具体的模型层设计方式要参见:M层的设计


欢迎大家关心自身的github地址,关注欧阳大哥2013,关注自我的简书地址:http://www.jianshu.com/u/3c9287519f58

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2018 亚洲必赢app官方下载 版权所有