架构模式:MVC与MVVM

  本文探讨如下几个问题:
  
  什么是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) => {www.mcyllpt.com 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 www.yigouyule2.cn Controller):处理应用程序所有类型请求的单个处理程序,应用程序可以是基于 web 的应用程序,也可以是基于桌面的应用程序。
  
  调度器(Dispatcher):前端控制器可能使用一个调度器对象来调度请求到相应的具体处理程序。
  
  视图(View):视图是为请求而创建的对象。
  
  在SpringMVC中:
  
  View:指的是各种展现模板,比如:velocity,freemark,www.dasheng178.com/  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"www.mcyllpt.com/>
  
  <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>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值