关于对MVC和MVVM的思考

时间:2023-03-09 16:25:42
关于对MVC和MVVM的思考

前言:最近公司交给我一个web项目,其采用的框架是java中的zkoss,它不用于以往我平时用的mvc,它采用的mvvm模式,因为以前只理解过mvc,经常使用譬如SpringMvc、Struts2等框架,对于mvc模式理解的较多,而这个zkoss框架则不用,它是基于ajax的,采用的是mvvm的模式(当然它也提供了mvc的模式,若想使用也可以)。今天就想来浅谈一下mvc和mvvm模式各自的优缺点和在项目中如何使用好它们。

本篇博客目录:

一:mvc模式

二:mvvm模式

三:mvc和mvvm模式各自的优点和不足

五:总结

一:mvc模式

1.1: MVC是一种经典的软件建造模式了,它主要分为三层,分别为Model、view、controller,其表示的含义是模型层、视图层、控制层,其中根据这三层又可以抽象出很多层来。但是其主要的思想是变的,像我们平时使用的框架SpringMvc、struts2等都是java web中的mvc框架, 遵循了mvc的设计范式。mvc模式的入口在view上,视图层也就是我们平时看到的网页页面,比如一个按钮、一个输入框、一个链接等可以看做是视图层的一部分,然后视图层直接和控制器打交道,一个web网站的最根本其实是实现数据的传输与流通,然后再把它返回给页面。当视图层问候控制器的时候,这个时候控制器去模型层去拿封装好的数据模型进行数据组装,如果涉及到数据的crud的话,我们需要再去把控制层进行再划分,常见的比如:Service、Dao、Controller,service层主要做的是封装业务逻辑的属性,而Dao层就是和数据库进行打交道了。这些再划分最终的目的也是更好的实现业务逻辑。

1.2:举个很简单的例子,首先用户通过点击web页面上的一个输入框,比如我们常用是上网场景是打开百度,在百度中输入一个关键字,那么百度就会呈现出根据这个关键字查询出来的结果网页(我们要做的是把值显示到一个p标签里),这其中百度网站又做了些什么呢?百度后台又是如何实现的呢?我们来简单的模拟一下(当然真实的百度可能并不是这样,这里只是举例说明):

<form action="search">
<input type="text" />
<input type="submit" />
</form>
<div>
<p id="p1"></p>
</div>

这是一个简单的form表单,当用户点击submit按钮的时候,这个form表单就会被提交到服务器,其中它会带着seacrh这个action,也就是一个请求来到我们的服务器中,假如我们采用的是Springmvc框架的话,那么此时会有一个控制器进行接收:一般的情况会如下

@Controller
public class SearchController{ @RequestMapping("search")
public String doSearch(@requestParam String input,Model model){ String result=doSearchService.search(input); model.serAttribute("userInput",result);
return "SearchRes";
}
}

这个控制器一般会映射search请求,拿到请求的参数,然后调用service进行查询,再把结果直接返回到SearchRes视图中,这个视图就可以访问model对象从而根据用户输入的值拿到结果返回给页面,这其中又要用到javaScript通过异步请求ajax来把值传递给p标签,改变它的innerHtml,从而完成赋值的过程。(这一步暂时省略)

二:mvvm模式

2.1:mvvm模式,望文生义,它主要分为model、view、viewModel.也就是数据模型、视图、视图+模型层,注意它不是四层而是三层。很多前端框架都采用了这种模式,比如:angular.js、konckoutJs等,它最大的好处就是可以实现自动绑定,将数据绑定在组件ui上,当UI中的值发生变化的时候,那么它对应的模型中的值也跟随发生变化,这也就是它双向绑定机制,原因在于它在视图层和数据模型层之间实现了一个绑定器,绑定器可以管理两个值,它一直监听组件UI的值,只要发生变化,它将会把值传输过去改变model中的值.绑定器比较灵活,还可以实现单向绑定。

关于对MVC和MVVM的思考

2.2:我们来按照mvvm模式来仿照一下刚才的mvc结构下的搜索的例子,这里用zkoss框架作为示范:

<textbox value="@binding(vm.UserInput)"/>

这是一个view层,zkoss采用是视图叫做zul,这串代码里它有一个textbox组件,也就是一个输入框,然后它的value值通过@binding注解绑定到viewmodel中的一个字段叫做UserInput,这个注解会自动实现当用户输入一个值的时候,它将会把值绑定在UserInput这个字段上,同样在viewmodel中UserInput这个字段的值发生改变的时候,前端Ui中组件的值也同样会跟随发生变化。这就间接节省了很多程序员的工作,比如在Servlet中我们还需要用String uiValue=request.getParamter("userinput");才能拿到它的值。

接下来,我们需要用过这个值然后进行查询。这里我们就可以采用mvc模式了,把mvvm得到的值视为一个model,然后让mvc去查询,查询后我们只需要把结果赋值给这个UserInput就可以了,它可以自动完成绑定,那么我们在页面中看到的是变化后的值。

public class SearchViewModel{

public String userInput;

@RequestMapping("search")
public String doSearch(@requestParam String input){ String result=doSearchService.search(input);

userInput=reslut; }
}

三:mvc和mvvm模式各自的优点和不足

3.1:mvvm的优点

3.1.1:mvvm自动绑定机制可以大大减少我们写代码的数量,很方便,一切都趋于自动化,数据跟随页面UI变化。而在mvc里面,你需要去通过方法去获取这个组件对应的值。一定程度上减少了我们的代码量,提高了编程效率

3.2.2:mvvm数据的一致性更高,因为在mvc模型里,很可能出现某个组件获取值的时候出现错误,而在mvvm就不存在这个问题,值和组件绑定就会保证获取的值是可靠并且一致的

3.2.3:mvvm更便于理解,程序员的学习成本较低,(但内部封装的比mvc模式要复杂),学习起来更简单

3.2:mvvm的缺点

3.2.1:正所谓越自动的东西越有出错的几率,mvvm的自动绑定机制,偶尔会出现一种不灵活的现象,数据绑定会失灵,我就遇见过这样的现象

3.2.2:mvvm构建的程序在vm会显得臃肿,因为所有的逻辑都集中在vm中了,而在mvc里面不存在这个问题。并且vm中的方法无法进行复用,你必须重新复制原来的方法属性才可以

3.2.3:mvvm做的程序的健壮性不如mvc,mvc的灵活、操作性较强,而mvvm在遇见一些复杂的组件上,无论是灵活度还是执行性都不如mvc,这点我深有体会,在Zkoss的框架使用中,遇见一些稍微比较复杂的业务逻辑的时候,发现我用mvvm根本无法实现,不得已转换到mvc的模式上

3.3:mvc的优点

3.3.1:mvc作为一种经典的web框架模型,它构建出的程序稳定可靠,并且具有很高的分层度,提起mvc我们经常想到的是业务层、逻辑层、Dao层,这种鲜明的分层架构给程序带来了高度可复用的好处,并且层次清晰,便于构建大型应用程序

3.3.2:mvc对于组件的操作性更好,擅于控制各种组件,并且组织各种关系数据对其进行高度可控的封装

3.3.3:mvc灵活度更高,对于同一个业务场景可以存在很多的实现方式,而mvvm就相对来说非常单一了

3.4:mvc的缺点

3.4.1:mvc模式要比mvvm写更多的代码,代码的可读性和便捷性上不如mvvm。

3.4.2:mvc模式一般实现起来更复杂,并没有mvvm那么相对来说比较轻量

3.4.3:mvc模式严格遵守这种模式,导致比较小的程序也得按照它的分层要求来实现,比较小的应用完全可以不采用它的分层结构(实现起来比较复杂),而他要求不论大小应用程序必须严格遵守分层的结构(当然任性也可以不遵守),比较微小的服务完全可以不用采用mvc模式,可以选择mvvm更快捷方便