百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

架构模式:MVC与MVVM(mvi架构)

ccwgpt 2024-10-16 08:12 35 浏览 0 评论

本文探讨如下几个问题:

  • 什么是MVC
  • 什么是MVVM
  • MVC与MVVM对架构属性的影响
  • MVC实例SpringMVC
  • MVVM实例Vue
  • MVC、MVVM与Layer中的Model,Controller有什么区别?

MVC与MVVM

在「什么是架构模式和架构风格」一文中,对架构模式的定义是:

Architecture Pattern: { Problem, Context } → architecture approach;

架构模式描述了一组组件之间的关系,用以解决特定上下文内的某个常见的架构问题

MVC和MVVM都是架构模式!

  • MVC描述了「Model,View,Controller」三者之间的关系,用以解决「有展示界面的系统」「界面开发与业务逻辑的耦合问题」
  • MVVM描述了[Model,View,ViewModel(和Binder)」三者之间的关系,用以解决「有展示界面的系统」「界面开发与业务逻辑的耦合问题」

可以看出MVC和MVVM都是为了解耦「界面」和「业务逻辑」,只是解决方案不同!也可以说MVVM是MVC的一种变体(ViewModel+Binder可以说是Controller的一种实现方式),或者衍生!

我们先说,为什么要解耦「界面」和「业务逻辑」?

早期的界面系统开发时,展示逻辑与数据是糅合在一起的!以早期的Java为例,所有的展示逻辑和业务逻辑都写在了Servlet/JSP中,导致了:

  • 单个文件的代码量较多,既包含了展示代码又包含了业务逻辑
  • 违背了职责单一性原则
  • 修改麻烦
  • 复用性差
  • 不易于维护
  • ......

MVC将系统拆分为控制器、视图和模型来解决上面的问题:

  • 控制器(Controller)- 负责转发请求,对请求进行处理。
  • 视图(View) - 界面设计人员进行图形界面设计。
  • 模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。

Wiki给出了一个Js模拟的MVC模式代码,能更清晰的理解三者之间的关系:

/** 模拟 Model, View, Controller */
var M = {}, V = {}, C = {};
/** Model 负责存放数据 */
M.data = "hello world";
/** View 负责将资料展示出来 */
V.render = (M) => { alert(M.data); }
/** Controller 作为M和V的桥梁 */
C.handleOnload = () => { V.render(M); }
/** 在页面加载的时候调用Controller*/
window.onload = C.handleOnload;

这样的拆分,提高了系统的:

  • 可扩展性:View、Model和Controller分别负责视图、数据和控制,可独立进化。能较方便的增加新功能。
  • 可维护性:结构清晰,多个View可以复用一个Model,减少了代码重复
  • 可测试性:每个组件的职责单一,可以对Model进行自动化测试
  • 灵活性:Controller 可以用来连接不同的 Model 和 View 去完成用户的需求
  • 可配置性:给定一些可重用的 Model 、 View 和Controller 可以根据用户的需求选择适当的 Model 进行处理,然后选择适当的的 View 来处理结果显示给用户

而MVVM模式将系统拆分为视图、模型和视图模型以及绑定器来解决耦合问题:

  • Model:Model是指代表真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心)。和MVC中的Model指代的内容相似。
  • View:就像在MVC中一样,View是用户在屏幕上看到的结构、布局和外观(UI)。
  • ViewModel:ViewModel是暴露公共属性和命令的视图的抽象。
  • Binder:绑定器是MVVM模式里的一个隐含组件,ViewModel中声明了数据与View之间的绑定关系,而绑定器来处理声明的绑定关系。

ViewModel和Binder的关系就像Java里的注解与注解处理器之间的关系:注解只是标示了某个字段、方法或某个类应该具备什么属性;注解处理器根据注解,对被注解的字段、方法或某个类来进行实际的处理。

这样的拆分,与MVC模式一样,提高了相同的系统属性,只是方式有一些差异:

  • 可扩展性:View、Model和ViewModel(和Binder)分别负责视图、数据和数据视图绑定,可独立进化
  • 可维护性:结构清晰,多个View可以复用一个Model,减少了代码重复
  • 可测试性:每个组件的职责单一,可以对Model进行自动化测试。前台也可以对ViewModel进行自动化测试。
  • 灵活性:ViewModel 可以用来绑定不同的 Model 和 View 去完成用户的需求
  • 可配置性:给定一些可重用的 Model 、 View可以根据用户的需求选择适当的 Model 进行处理,然后选择适当的的 View 来处理结果显示给用户

SpringMVC

SpringMVC是目前使用比较广泛的MVC框架!它是MVC与「前端控制器」的混合体!

前端控制器模式(Front Controller Pattern)是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。前端控制器包含如下组件:

前端控制器(Front Controller):处理应用程序所有类型请求的单个处理程序,应用程序可以是基于 web 的应用程序,也可以是基于桌面的应用程序。

调度器(Dispatcher):前端控制器可能使用一个调度器对象来调度请求到相应的具体处理程序。

视图(View):视图是为请求而创建的对象。

在SpringMVC中:

  • View:指的是各种展现模板,比如:velocity,freemark,theamleaf等
  • Controller:指的是前端控制器与Controller层
  • Model:指的是Controller后的后续处理组件,比如Service,Model,Domain,DAO层等

SpringMVC的前端控制器做了很多事情,结构如下图:

  • HandlerMappingMap: 维护了请求与处理程序(一组前置拦截器+处理程序+后置拦截器)之间的关系,如何维护映射关系,由具体的实现决定。例如:RequestMappingHandlerMapping基于@RequestMapping注解来维护映射关系;SimpleUrlHandlerMapping根据URI匹配关系来处理映射关系
  • HandlerAdapter:用于执行具体的处理程序。由于不同的映射关系,执行处理程序的方式也不一样,HandlerAdapter封装了这些执行差异
  • HandlerException:异常处理程序,将异常映射到处理程序、或HTML或其它组件上。即可以通过配置,统一的处理某一种类型的异常
  • ViewResolver:通过解析「基于字符串的视图名称」来找到真实的视图,来进行渲染,回写到响应中
  • LocaleResolver, LocaleContextResolver:处理国际化
  • ThemeResolver:处理主题
  • MultipartResolver:处理multi-part请求 (上传文件)
  • FlashMapManager:实现Flash作用域。因为标准J2EE中只提供了page,request,session,application四种作用域。Spring通过FlashMapManager实现了Flash作用域,用于在单个请求内传递参数。

Vue

Vue实现的是MVVM模式!

在Vue中:

  • View:指的是各种template,即基于html语法的展示
  • ViewModel:指的是对应的js,声明绑定的元素及绑定的数据
  • Binder:处理template与js的绑定逻辑
  • Model:指的是获取数据的逻辑。如果使用的是node,则就是node相关逻辑代码;如果调用的是远程服务,则指的是远程服务

一个简单的Vue代码如下:

<!DOCTYPE html>
<html lang=en>
 <head>
 <meta charset="utf-8"/>
 <title>Hello world</title>
 <script src="vue.js"></script>
 </head>
 <body>
 <div id="app">{{content}}</div>
 <script>
 var app = new Vue({
 el:'#app', //vue实例处理哪个dom
 data:{ //定义
 content:'hello world'
 },
 methods:{
 fetchData: function() {
 // 获取数据
 }
 }
 });
 </script>
 </body>
</html>

下图是Vue的生命周期:

  • Vue对象就是ViewModel,它声明了:
  • 要处理哪个dom「el」
  • 有哪些数据「data」
  • 有哪些方法「methods」
  • 生命周期钩子(beforeCreate,created...)
  • Binder(Vue框架处理代码)根据上面的生命,来进行相应的处理

此Model非彼Model

在上面有三处提到了Model和Controller,这三处的Model和Controller并不完全相同!

三处Model:

  • MVC中的Model:这里的Mode指的是提供数据相关服务的组件。或者说是业务处理逻辑。
  • MVVM中的Model:和MVC一致
  • 系统中的Model:指的是分层系统中的Model层(代码分层),主要作为系统与持久层的数据载体,可以是只有get、set方法的POJO也可以是包含领域方法的领域对象

三处Controller:

  • MVC中的Controller:指的是连接View和Model的组件
  • Spring中的前端控制器:Controller的一种实现,统一处理请求
  • Spring中的Controller:分层系统里的Controller层(代码分层,可能叫Handler更合适),属于MVC中的Controller

参考资料

- [Wiki MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)

- [SpringMVC](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html)

- [Wiki MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel)

- [FrontController](http://www.runoob.com/design-pattern/front-controller-pattern.html)

相关推荐

用Steam启动Epic游戏会更快吗?(epic怎么用steam启动)

Epic商店很香,但也有不少抱怨,其中一条是启动游戏太慢。那么,如果让Steam启动Epic游戏,会不会速度更快?众所周知,Steam可以启动非Steam游戏,方法是在客户端左下方点击“添加游戏”,然...

Docker看这一篇入门就够了(dockerl)

安装DockerLinux:$curl-fsSLhttps://get.docker.com-oget-docker.sh$sudoshget-docker.sh注意:如果安装了旧版...

AYUI 炫丽PC开发UI框架2016年6月15日对外免费开发使用 [1]

2016年6月15日,我AY对外发布AYUI(WPF4.0开发)的UI框架,开发时候,你可以无任何影响的去开发PC电脑上的软件exe程序。AYUI兼容XP操作系统,在Win7/8/8.1/10上都顺利...

别再说C#/C++套壳方案多了!Tauri这“借壳生蛋”你可能没看懂!

浏览器套壳方案,C#和C++有更多,你说的没错,从数量和历史积淀来看,C#和C++确实有不少方式来套壳浏览器,让Web内容在桌面应用里跑起来。但咱们得把这套壳二字掰扯清楚,因为这里面学问可大了!不同的...

OneCode 核心概念解析——Page(页面)

在接触到OneCode最先接触到的就是,Page页面,在低代码引擎中,页面(Page)设计的灵活性是平衡“快速开发”与“复杂需求适配”的关键。以下从架构设计、组件系统、配置能力等维度,解析确...

React是最后的前端框架吗,为什么这么说的?

油管上有一位叫Theo的博主说,React是终极前端框架,为什么这么说呢?让我们来看看其逻辑:这个标题看起来像假的,对吧?React之后明明有无数新框架诞生,凭什么说它是最后一个?我说的“最后一个”不...

面试辅导(二):2025前端面试密码:用3个底层逻辑征服技术官

面试官放下简历,手指在桌上敲了三下:"你上次解决的技术难题,现在回头看有什么不足?"眼前的候选人瞬间僵住——这是上周真实发生在蚂蚁金服终面的场景。2025年的前端战场早已不是框架熟练...

前端新星崛起!Astro框架能否终结React的霸主地位?

引言:当"背着背包的全能选手"遇上"轻装上阵的短跑冠军"如果你是一名前端开发者,2024年的框架之争绝对让你眼花缭乱——一边是React这位"背着全家桶的全能选...

基于函数计算的 BFF 架构(基于函数计算的 bff 架构是什么)

什么是BFFBFF全称是BackendsForFrontends(服务于前端的后端),起源于2015年SamNewman一篇博客文章《Pattern:BackendsFor...

谷歌 Prompt Engineering 白皮书:2025年 AI 提示词工程的 10 个技巧

在AI技术飞速发展的当下,如何更高效地与大语言模型(LLM)沟通,以获取更准确、更有价值的输出,成为了一个备受关注的问题。谷歌最新发布的《PromptEngineering》白皮书,为这一问题提供了...

光的艺术:灯具创意设计(灯光艺术作品展示)

本文转自|艺术与设计微信号|artdesign_org_cn“光”是文明的起源,是思维的开端,同样也是人类睁眼的开始。每个人在出生一刻,便接受了光的照耀和洗礼。远古时候,人们将光奉为神明,用火来...

MoE模型已成新风口,AI基础设施竞速升级

机器之心报道编辑:Panda因为基准测试成绩与实际表现相差较大,近期开源的Llama4系列模型正陷入争议的漩涡之中,但有一点却毫无疑问:MoE(混合专家)定然是未来AI大模型的主流范式之一。...

Meta Spatial SDK重大改进:重塑Horizon OS应用开发格局

由文心大模型生成的文章摘要Meta持续深耕SpatialSDK技术生态,提供开自去年9月正式推出以来,Meta持续深耕其SpatialSDK技术生态,通过一系列重大迭代与功能增强,不断革新H...

&quot;上云&quot;到底是个啥?用&quot;租房&quot;给你讲明白IaaS/PaaS/SaaS的区别

半夜三点被机房报警电话惊醒,顶着黑眼圈排查服务器故障——这是十年前互联网公司运维的日常。而现在,程序员小王正敷着面膜刷剧,因为公司的系统全"搬"到了云上。"部署到云上"...

php宝塔搭建部署thinkphp机械设备响应式企业网站php源码

大家好啊,欢迎来到web测评。本期给大家带来一套php开发的机械设备响应式企业网站php源码,上次是谁要的系统项目啊,帮你找到了,还说不会搭建,让我帮忙录制一期教程,趁着今天有空,简单的录制测试了一下...

取消回复欢迎 发表评论: