MVVM的优点和缺点

简介: MVVM的优点和缺点

MVVM的典型开源项目下载地址:https://github.com/kopuCoder/SXNews。

MVVM( Model-View-ViewModel子控件的事件驱动模型),也就是轻量级的控制器架构。它本质上就是MVC的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。Model就是Entity,定义数据;View实现视图 UI;ViewModel负责请求发送及业务逻辑;UIViewController只负责生成数据(Model),View(视图 UI),ViewModel(请求发送及业务逻辑)三者的对象与协调他们完成具体的页面。

软件开发人员的两种典型错误思维

1.头脑风暴。

2.盲目反对。

纯粹的头脑风暴会让你只看到软件方案和架构的优点,避而不谈它的缺点。软件不可能永远存在云上,它会落地的,当它落地时,会出现这样和那样的问题。

盲目的反对更要不得,这也不行,那也不行,只看一种方案和架构的缺点,看不到优点,那不是什么都不要做了。每个人由于习惯使然会偏向这两种做法,需要从心理上克服这种偏颇,采用包容的心态。

苹果客户端开发的三种境界

1.无明显架构的无序开发(新人的初始状态),想的是MVC架构开发,由于技术知识不足或懒惰,只追求速度,把一个页面所有的逻辑和控件都在该页面的控制器里完成,不去抽象控件,不去抽象模块。一个xib和控制器包打一个页面的天下。这样的架构和思维要不得,可以当自己学习新技术使用,不要用到具体的软件开发中去。

2.MVC(Model View Controller)架构开发,它是苹果推荐的开发模式,它把页面分成三部分:数据模型,页面视图,页面控制器。一个页面被分成多个小视图,一个页面共享一个数据模型,只是这个数据模型只被控制器操作,不被各个子视图处理。这个架构看起来整洁多了,控制器的复杂度降低的很多,页面的显示单元被分配到各个视图去显示,控制器专注与数据的加工与处理,部分解放了控制器,使它的功能更集中,更紧凑,更小。数据模型,页面视图,页面控制器各个独立,各司其职。这就是重量级视图控制的特点。它看起来简单,更容易理解,所有的逻辑在视图控制器里处理。一个页面一般分三个文件夹:页面文件夹(存放页面控制器和其子文件夹),页面文件夹下的model文件夹,页面文件夹下的view文件夹。想找页面间的逻辑就去页面控制器里找,想看页面显示元素就在view文件夹下寻找。你发现数据文件很小,只是数据存储和转换,这符合数据单一性原则;视图部分也很小,只是数据的显示,完全不自主;控制器部分仍然摆脱不了过于庞大的弊病。他们就像一个人一样头重而且庞大,脚轻,身子小。看到这些你就知道这种开发架构需要进化的方向:强化控制器的重要性,减轻它的体积,把不属于它的非核心部分迁移到类似视图的那一部分去,在保证数据的定义性上增加它的功能和作用。取消使用单例组装http请求的做法(单例像类一样常驻内存,无形中增加类内存的开销。虽然它做到了统一管理http请求的作用,但是不符合那个页面的请求那个页面管理请求的原则)。让从控制器分化出来的这一部分功能给View,http请求封装为一个新操作类。


3.MVVM( Model View-Model Controller View)就是MVC设计模式的更先进进化,符合它进化的方向。每个人对MVVM了解不同和使用技术不同,最终实现的MVVM架构也不同。

数据源被强化,不单只是请求过来的数据还包括,数据在本页面应该处于的状态(例如:根据请求,支付页面是企业支付,不需要显示第三方支付选择框,model增加了这样的状态。当然这样的状态可以改变,用户重新选择了支付方式,选择个人支付,该状态要根据用户的行为而改变。),数据源对象在本页面或本模块中共享,一旦一个地方改变,本页面或模块中的所有数据源的内容都改变,保证了数据的一致性。它的全局共享性是它的一大特色。

从控制器分离出来的非页面间关系部分和http请求部分,产生请求操作类.它可以被控制器调用,也可以被view调用。它负责数据数据请求参数的组装,甚至上次请求的暂存,服务器请求过来的数据转化为数据源数据,进行简单数据处理。我们称它为View-Model。一个页面可以有一个View-Model,也可以有多个View-Model,这个可以根据页面的复杂度和View(调用View-Model的View)是否在其它页面重用。若有View调用请求对象发送请求并且被其它页面重用该View,那么该View不能共享数据源。View-Model一般持有本页面或本模块的共享数据源。

控制器专注于自己的核心功能:页面的跳转,跨本页面多个视图的操作,数据源数据的初始化,从上一个页面接收数据转化为本页面的数据源(有的页面不发送请求只是显示数据,有的页面需要上也个页面接收关键字段(如“订单号)作为本页面请求的参数),子视图页面的创建和布局,子视图页面的block函数,状态栏,导航栏,页面跳转方式(有的页面需要跳转后销毁本页面—地图页面);有的页面出现后需要常驻内存,不能销毁本页面–Tabbar页面),在dealloc中销毁移除通知。除了这些核心事件外,其它的都可以移置到View或View-Model中处理。控制器持有本页面或本模块的共享数据源。

控制器相对的并不是只有父类为UIViewController的类才是控制器。当也个页面过于复杂,被分成了多个层次时,可以通过在[[[UIApplication sharedApplication] delegate] window]增加view。这个新增加的View本身就和控制器的功能一样。这个可以做到一层页面就是一个控制器。

当然也可以下面的方法创建window。这个window也是和控制器一致。 self.currentWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, FULL_WIDTH, FULL_HEIGHT)];

self.currentWindow.windowLevel = UIWindowLevelStatusBar;

self.currentWindow.opaque = NO;

[self.currentWindow makeKeyAndVisible];若用创建window的方法创建视图控制器时需要在销毁这个window时调用[[[[UIApplication sharedApplication] delegate] window] makeKeyAndVisible];来使原来的window显示。由于该方法实际上向主线程发送的一个通知,等刷新UI线程调用了响应的处理才执行,就是它是异步执行的,所以当页面首次加载时有可能页面显示不出来的情况。所以这种方法建议慎用,采用上一种方法更安全。

View增强了两大功能:持有全局数据源,根据数据源进行显示和布局;可以直接调用请求对象发送请求,来刷新数据或页面跳转。可以看到View已经具有部分控制器的功能(调用View-Model发送http请求,刷新页面),并且View根据抽象的需要可以在不同页面或模块间共享使用。

MVVM一般包含页面(或模块)总文件夹,Entity文件夹(model对象或模块内的编译宏),View文件夹(视图文件,该文件夹下可能包含子ViewModel文件夹),图片库(Assets.xcassets),ViewController文件夹(控制器对象),ViewModel文件夹(http请求对象)。除了这个5个基本文件夹外还可能包含序列化model的文件夹。

MVVM设计模式的优点

1.双向绑定技术,当Model变化时,View-Model会自动更新,View也会自动变化。很好做到数据的一致性,不用担心,在模块的这一块数据是这个值,在另一块就是另一个值了。所以 MVVM模式有些时候又被称作:model-view-binder模式。

2.View的功能进一步的强化,具有控制的部分功能,若想无限增强它的功能,甚至控制器的全部功几乎都可以迁移到各个View上(不过这样不可取,那样View干了不属于它职责范围的事情)。View可以像控制器一样具有自己的View-Model.

3.由于控制器的功能大都移动到View上处理,大大的对控制器进行了瘦身。不用再为看到庞大的控制器逻辑而发愁了。

4.可以对View或ViewController的数据处理部分抽象出来一个函数处理model。这样它们专职页面布局和页面跳转,它们必然更一步的简化。

【长篇高能】ReactiveCocoa 和 MVVM 入门(http://www.cocoachina.com/ios/20150526/11930.html)就是MVVM设计模式头脑风暴提唱者。其实它没有那么神,它也有很多固有的缺点,而且有的优点其实也是缺点,并且不容易改进。

MVVM设计模式的缺点

第一点:数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。

第二点:一个大的模块中,model也会很大,虽然使用方便了也很容易保证了数据的一致性,当长期持有,不释放内存,就造成了花费更多的内存。

第三点:数据双向绑定不利于代码重用。客户端开发最常用的重用是View,但是数据双向绑定技术,让你在一个View都绑定了一个model,不同模块的model都不同。那就不能简单重用View了。

被误解的MVC和被神化的MVVM(http://www.infoq.com/cn/articles/rethinking-mvc-mvvm/)这篇文章是MVVM彻头彻尾的反对者,好像该设计模式一文不值。我只能说他太偏激了,只顾着指责,没有看到他最显然的优点和改进。

MVVM设计模式的优缺点之我见及改进

MVVM更高级更先进表现在解放了控制器(Controller),就是轻量级控制器。这个批评者也没有否定。MVVM不影响代码重用,其实抽象出来的一个一个小View就是为了代码重用的。反对者所谓的把网络请求封装到类里也就是View-Model。

其实对它贬低最多的只剩下集优缺点于一身的双向绑定技术。那么他们也不治之症,也可以改进。

对于调试困难的问题,确实存在,可以通过日志系统来定位,对数据被修改的地方进行敏感的地方进行日志打印。不会你的软件没有日志系统吧?

对于影响内存问题,你可以通过划分模块时,把一个页面或两到三个页面划分为一个模块,那样应用的model也不大,内存开销很小。我大都把每个页面多划分一个模块,减少耦合度,软件开发的高内聚低耦合的设计思想大家都懂吧!若把一个项目的数据都整合到一个面面俱到的model, 那除非傻子才那么做,就是那样做了,那也不符合MVVM模式了。

对于数据双向绑定不利于代码重用确实是一个问题。基本上重用的代码model都不相同。你可以对这两个model抽象成一个组合model.也可以观察你这个View需要哪些必须的数据,把它当变成成员变量,让他不绑定model.若这个View在两个模块使用,并且发送请求,那么你可以给这个View抽象为一个新的View-Model.

若真像《被神化的MVVM》那篇文章说的那样改进MVC设计模式,那么它就不是 MVC了,它更像不采用ReactiveCocoa的 MVVM了。

【长篇高能】ReactiveCocoa 和 MVVM 入门这篇文章给我们影响最深刻的是ReactiveCocoa的一切皆信号。其实也就是封装了一层block,没有什么神秘的,不过使用起来确实方便,值得推荐,若你会使用原来的老方式也没有什么掉价,并不是你不是你不使用ReactiveCocoa就不是 MVVM.它说了半天完了半天文字动画也没有说明 MVVM的本质,它的本质其实就抽像出来http请求类,增强View的功能,让它像控制器一样发送请求和刷新UI,甚至跳转页面。但是它说出了MVC向MVVM进化的根本方向:对控制器瘦身,增强View的功能,数据双向绑定。但是最关键是只说了优点,没有说它的缺点。兼听则明,偏信者暗。

我相信MVVM比MVC设计模式更先进,值得推荐,ReactiveCocoa 有助于MVVM的使用,它的另一个优点,更有助于模块化。并非文章说为了实现一切皆信号的境界。

既然ReactiveCocoa能有现成的实现MVVM设计模式的方案,而且便于实现软件模块化。那么没有必要必要盲目的反对,可以欣然接受,但是还没有达到盲目非使用不的地步。使用该设计方案,就要用到pods,不然很麻烦,我没有试过替代方案。

我们应该跳出方法论的怪圈,致力那种方案能使我们的软件更容易理解,更容易模块化就用那种方案。使用ReactiveCocoa会引入它的框架,需要使用pods。你不会可能感觉到心理上抗拒采用该技术,一旦你引入了该框架,学会了该技术,它会一劳永远给你以后的开发带来很多方便。


目录
相关文章
|
C# 开发者
C# 9.0中的模块初始化器:程序启动的新控制点
【1月更文挑战第14天】本文介绍了C# 9.0中引入的新特性——模块初始化器(Module initializers)。模块初始化器允许开发者在程序集加载时执行特定代码,为类型初始化提供了更细粒度的控制。文章详细阐述了模块初始化器的语法、用途以及与传统类型初始化器的区别,并通过示例代码展示了如何在实际项目中应用这一新特性。
|
PHP Python
矩阵制度三三复制直销系统模式开发详解 | 矩阵制度三三复制直销系统开发源码demo示例
矩阵制度三三复制模式是一种常见的直销模式,也被称为三三复制模式。该模式限制了前排的数量,只能填满3个位置,奖金则是按照固定的深度来进行领取的。在该模式中,每个参与者都可以推荐其他人加入,如果成功推荐,就可以获得相应的奖金。具体来说,如果推荐一个参与者,可以获得20美元的奖金;如果推荐两个参与者,可以获得10美元的奖金;如果推荐三个参与者,可以获得4美元的奖金。此外,该模式还有一些其他的奖金制度,如培育奖金、扣税等。
|
C# 前端开发
WPF中Style文件的引用——使用xaml代码或者C#代码动态加载
原文:WPF中Style文件的引用——使用xaml代码或者C#代码动态加载   WPF中控件拥有很多依赖属性(Dependency Property),我们可以通过编写自定义Style文件来控制控件的外观和行为,如同CSS代码一般。
5227 0
|
人工智能 Java 测试技术
通义灵码2.0·AI程序员加持下的智能编码实践与测评
通义灵码2.0是阿里云推出的新一代智能编程助手,集成DeepSeek模型并新增多项功能,显著提升开发效率。本文通过实际项目体验新功能开发、跨语言编程、单元测试自动生成和图生代码等功能,展示其在代码生成、质量内建和人机协作方面的优势。相比1.0版本,2.0在模型选择、代码质量和用户体验上均有显著提升。尽管存在依赖网络和多语言混合项目中的不足,但整体表现优异,极大优化了开发流程。[了解更多](https://lingma.aliyun.com/)
1557 59
|
存储 人工智能 数据管理
云端问道17期方案教学-AI场景下的对象存储OSS数据管理实践
本文介绍了AI场景下的对象存储OSS数据管理实践,由阿里云技术专家明锦分享。主要内容分为两部分:1) AI场景下对象存储实践方案,包括对象存储的应用、优势及在模型推理中的优化;2) OSS常用工具介绍,如OSSFS、Python SDK、Go SDK等,并详细说明了这些工具的特点和使用场景。文中还探讨了不同模式下的性能优化,以及即将推出的OS Connector for AI/ML工具,旨在提升数据下载速度和IO性能。
422 0
|
前端开发 JavaScript 程序员
HarmonyOS NEXT开发-ArkTS五
本文介绍了ArkTS中的联合类型和枚举类型,讲解了定义与使用方法,并详细阐述了模块的导出与导入(包括静态导入、动态导入及HarmonyOS SDK的开放能力导入),帮助开发者更好地理解和应用这些特性。君志所向,一往无前!
326 0
HarmonyOS NEXT开发-ArkTS五
|
Kubernetes API Docker
在K8S中,如何查看kubelet组件的日志?
在K8S中,如何查看kubelet组件的日志?
|
存储 前端开发 测试技术
MVC、MVP、MVVM 模式
MVC、MVP 和 MVVM 是三种常见的软件架构模式,用于分离用户界面和业务逻辑。MVC(Model-View-Controller)通过模型、视图和控制器分离数据、界面和控制逻辑;MVP(Model-View-Presenter)将控制逻辑移到 Presenter 中,减少视图的负担;MVVM(Model-View-ViewModel)通过数据绑定机制进一步解耦视图和模型,提高代码的可维护性和测试性。
|
开发者
鸿蒙next版开发:ArkTS组件通用属性(菜单控制)
在HarmonyOS 5.0中,ArkTS引入了灵活的菜单控制属性,支持通过长按、点击或鼠标右键触发弹出式菜单,增强用户交互体验。本文详细介绍了bindMenu和bindContextMenu方法,以及MenuItem的配置属性,并提供了示例代码,帮助开发者更好地理解和使用这些功能。
893 1
|
SQL XML Java
Android 这 13 道 ContentProvider 面试题,你都会了吗?
Android 这 13 道 ContentProvider 面试题,你都会了吗?