草庐IT

MVC、MVP、MVVM模式的概念与区别

小M乱记 2023-04-05 原文

------《MVC、MVP、MVVM模式的概念与区别》

前言:

        首先MVC,MVP,MVVM都是为了解决UI页面与逻辑代码分离而出现的模式,MVP和MVVM都是MVC的基础上演化而来。他不属于某种语言的框架,只要是有UI页面与逻辑代码我们都可以使用这几种框架去搭建我们的项目。他是一种框架模式。
        M和V分别指Model层和View层,但其功能会因为框架的不同而变化。Model层是数据模型,用来存储数据;View层是视图,展示Model层的数据。
        虽然在不同的MV(XX)框架中,Model层和View层的内容可能会有所差别,但是其基础功能不变,变的只是 数据的传输方式 。

预热:

        MVC —— Model-View-Controller: 作为 Controller 层的 Actvity/Fragment 等充当了 View 的角色,代码过于臃肿;同时在 View 层又容易直接操作 Model,导致 View 和 Model 层耦合,无法独立复用。有时候看到一个 Activity 能有几千甚至上万行的代码,简直噩梦。
        MVP —— Model-View-Presenter: Presenter 和 View 层之间通过定义接口实现通信,解耦了 View 和 Model 层。然而当业务场景比较复杂时,接口定义会越来越多,且可能定义模糊,接口一旦变化,对应实现也需要发生变化。
        MVVM —— Model-View-ViewModel: MVVM 解决了 MVP 的问题,使得 ViewModel 和 View 之间不再依赖接口通信,而是通过 LiveData, RxJava, Flow 等响应式开发的方式来通信。
        MVI —— (后面单讲)

挨个讲讲:

MVC

        MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写
        Model:模型层,数据模型及其业务逻辑,是针对业务模型建立的数据结构,Model与View无关,而与业务有关。
        View:视图层,用于与用户实现交互的页面,通常实现数据的输入和输出功能。
        Controller:控制器,用于连接Model层和View层,完成Model层和View层的交互。还可以处理页面业务逻辑,它接收并处理来自用户的请求,并将Model返回给用户。

优点:
耦合性低,生命周期成本低,部署快,可维护性高,适用于快速开发的小型项目
缺点:
不适合大型,中等项目,View层Controller层连接过于紧密
View层对Model层的访问效率低
一般的高级UI页面工具和构造器不支持MVC模式

MVP

        MVP全名是Model View Presenter,是模型(model)-视图(view)-表示器(Presenter)的缩写
        Model:模型层,用于数据存储以及业务逻辑。
        View:视图层,用于展示与用户实现交互的页面,通常实现数据的输入和输出功能。
        Presenter:表示器,用于连接M层、V层,完成Model层与View层的交互,还可以进行业务逻辑的处理。

执行流程:
1、View层收到用户的操作
2、View层把用户的操作交给Presenter
3、Presenter直接操作Model层进行业务逻辑处理
4、Model层处理完毕后,通知Presenter
5、Presenter收到通知后,去更新View层
        在MVP模式中,Model与View无法直接进行交互,所以Presenter层会从Model层获得数据,适当处理后交给View层进行显示
在MVP模式中,Presenter层将View层和Model层进行隔离,使View和Model之间不存在耦合,同时将业务逻辑从View层剥离
优点:
        可以更高效的使用Model,所有的交互都发生在——Presenter内部
        将一个Presenter用于多个视图,而不需要改变Presenter的逻辑,View变化比Model变化频繁,逻辑结构清晰,View层代码不再臃肿
缺点:
1、MVP模式基于接口设计,会增加很多类,代码逻辑虽然清晰,但代码量庞大
2、MVP适用于中小型项目,大型项目慎用
3、MVC和MVP的主要区别:
4、MVP中View与Model并不直接交互,而是通过与Presenter交互来与Model间接交互
5、MVP中Controller是基于行为的,并且可以被多个View共享,Controller可以负责决定显示哪个View
6、MVP中Presenter与View的交互是通过接口来进行的,更有利于添加单元测试。
7、MVC中View可以与Model直接交互,通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑

MVVM

MVVM 即 Model-View-ViewModel
        M——Model(模型)实体模型,定义实体类,获取业务数据模型,如通过数据库或者网络来操作数据等
        V——View(视图)布局文件(XML),主要进行控件的初始化设置
        VM——ViewModel(控制器):连接 View 与 Model 的中间桥梁,ViewModel 与 Model 直接交互,通过DataBinding将数据变化反应给View

        存在两个方向都实现的情况,叫做数据的双向绑定。双向数据绑定可以说是一个模板引擎,它会根据数据的变化实时渲染。如图3.3所示,View层和Model层之间的修改都会同步到对方。
        双向绑定ViewModel+LiveData+DataBinding的形式上一篇已经讲了哦

优点:

  1. 结构清晰,职责划分清晰
  2. 模块间充分解耦
  3. 在 MVP 的基础上,MVVM 把 View 和 ViewModel 也进行了解耦
    缺点:
    1、定位问题困难

结尾:

        从MVC到MVP再到MVVM,这是一个不断进步的过程,后两者都是在MVC基础上发展而来,使用起来更加方便。这三者主要的区别在于除Model层和View层之外的第三层的不同。

有关MVC、MVP、MVVM模式的概念与区别的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  5. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  6. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  7. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  8. spring.profiles.active和spring.profiles.include的使用及区别说明 - 2

    转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev

  9. ruby - 这两段代码有什么区别? - 2

    打印1:defsum(i)i=i+[2]end$x=[1]sum($x)print$x打印12:defsum(i)i.push(2)end$x=[1]sum($x)print$x后者是修改全局变量$x。为什么它在第二个例子中被修改而不是在第一个例子中?类Array的任何方法(不仅是push)都会发生这种情况吗? 最佳答案 变量范围在这里无关紧要。在第一段代码中,您仅使用赋值运算符=为变量i赋值,而在第二段代码中,您正在修改$x(也称为i)使用破坏性方法push。赋值从不修改任何对象。它只是提供一个名称来引用一个对象。方法要么是破坏性

  10. ruby - Ruby 中 .next 和 .succ 的区别 - 2

    Ruby中的Fixnum方法.next和.succ有什么区别?看起来它的工作原理是一样的:1.next=>21.succ=>2如果有什么不同,为什么有两种方法做同样的事情? 最佳答案 它们是等价的。Fixnum#succ只是Fixnum#next的同义词。他们甚至在thereferencemanual中共享同一block. 关于ruby-Ruby中.next和.succ的区别,我们在StackOverflow上找到一个类似的问题: https://stacko

随机推荐