MVC简介
以淘宝的购物车为例
一、结合六个基本质量属性
可修改性
采用MVC设计模式的时候,可以将视图、模型、控制器分析,将用户动作、数据表示、应用数据分离开来,如果用户需要以不同的视图来展示,只需要修改视图中的代码即可,对于模型和控制器的代码,则不需要做改动,即可满足要求,使得对代码的修改非常方便。
易用性
用户可以直接在商品展示界面中将商品添加进购物车,直接点开购物车就可以看到已经添加的商品;删除某一件商品时,也可以直接在商品的后面点击删除,确认之后,即可删除。
安全性
实行对不同角色的不同权限的管理,比如买家账号和卖家账号,登录之后,对应的不同权限的操作。
可用性
淘宝实现7*24的可用性,如果某一个环节出了问题,使用MVC设计模式也可以快速的进行修复。
二、MVC设计模式具体在淘宝购物车当中的应用。
每个层大概的负责的职责,以及之间的关系。
假如以超市为例,进行购物流程,大概流程是:取得空购物篮—向购物篮中增减商品—结账,我们对这个流程进行分析可以发现,用户需要随时了解的信息是放入购物篮里的商品的品名、数量以及价格,在挑选商品阶段关注的是商品的品名、单价和数量,在结帐时关注的是商品的总计价格,这些信息与购物篮中的物品有直接相关。伴随着这个流程的是空购物篮的取得、购物篮内商品的增减、购物篮在结帐后被清空这样几个状态。可以发现,购物篮是整个购物交易过程中用户关注信息和购物流程状态变化的重要组成部分。我们可以用模型来表示购物篮,这个类设计中应包含商品信息、价格和数量属性,同时还要定义附加在属性上的商品加入、删除、价格计算等方法。用户的购物动作导向触发不同的方法以确定购物篮模型的不同的状态,而购物篮模型的状态变化应该能及时反映到用户界面,透过用户界面,可以了解到购物篮的信息,同时发出用户的动作指令。我们可以采用多个不同的类,以视图的方式来定义用户界面,以控制器的方式定义用户购物流程控制。
利用MVC设计模式,可以方便地设计出用于购物过程的相应的类和对象,并以比较合理的方式将它们组织起来。在电子商务系统的研究中,实现系统代码时,我们采用JSP实现用户视图,JSP和JavaBean作为模型,Servlet实现控制器,可以进行实现。
在浏览器的jsp页面中显示商品的信息,用户在界面中进行添加商品操作之后,到达servlet控制器,然后选择相应的购物篮模型,可能会与数据库进行交互,完成之后,再在购物车页面中进行显示出来。
MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。
MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器。
使用的MVC的目的:在于将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如Windows系统资源管理器文件夹内容的显示方式,下面两张图中左边为详细信息显示方式,右边为中等图标显示方式,文件的内容并没有改变,改变的是显示的方式。不管用户使用何种类型的显示方式,文件的内容并没有改变,达到M和V分离的目的。
在网页当中,
V即View视图是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操纵的方式。
M即model模型是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
C即controller控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
下图说明了三者之间的调用关系。
用户首先在界面中进行人机交互,然后请求发送到控制器,控制器根据请求类型和请求的指令发送到相应的模型,模型可以与数据库进行交互,进行增删改查操作,完成之后,根据业务的逻辑选择相应的视图进行显示,此时用户获得此次交互的反馈信息,用户可以进行下一步交互,如此循环。
MVC举例一:
最典型的MVC就是jsp+servlet+javabean模式。
JavaBean作为模型,既可以作为数据模型来封装业务数据,又可以作为业务逻辑模型来包含应用的业务操作。其中,数据模型用来存储或传递业务数据,而业务逻辑模型接收到控制器传过来的模型更新请求后,执行特定的业务逻辑处理,然后返回相应的执行结果。
JSP作为表现层,负责提供页面为用户展示数据,提供相应的表单(Form)来用于用户的请求,并在适当的时候(点击按钮)向控制器发出请求来请求模型进行更新。
Serlvet作为控制器,用来接收用户提交的请求,然后获取请求中的数据,将之转换为业务模型需要的数据模型,然后调用业务模型相应的业务方法进行更新,同时根据业务执行结果来选择要返回的视图。
MVC举例二:
Struts2框架:Struts2是基于MVC的轻量级的web应用框架。Struts2的应用范围是Web应用,注重将Web应用领域的日常工作和常见问题抽象化,提供一个平台帮助快速的完成Web应用开发。基于Struts2开发的Web应用自然就能实现MVC,Struts2着力于在MVC的各个部分为开发提供相应帮助。
下面通过代码来简单解释一下:
Login.html
Login.java
Struts.xml
用户首先在Login.html中输入用户名和密码,点击登陆,此时根据action的路径,在struts.xml中找到对应的Login,然后根据对应的class的路径进入相应的login.Java,在这里判断之后,返回success或error,然后根据struts.xml中的result值,指向相应的jsp页面。
控制器——filterdispatcher
从上面这张图来看,用户请求首先到达前端控制器FilterDispatcher。FilterDispatcher负责根据用户提交的URL和struts.xml中的配置,来选择合适的动作(Action),让这个Action来处理用户的请求。FilterDispatcher其实是一个过滤器(Filter,servlet规范中的一种web组件),它是Struts2核心包里已经做好的类,不需要我们去开发,只是要在项目的web.xml中配置一下即可。FilterDispatcher体现了J2EE核心设计模式中的前端控制器模式。
动作——Action
在用户请求经过FilterDispatcher之后,被分发到了合适的动作Action对象。Action负责把用户请求中的参数组装成合适的数据模型,并调用相应的业务逻辑进行真正的功能处理,获取下一个视图展示所需要的数据。Struts2的Action,相比于别的web框架的动作处理,它实现了与Servlet API的解耦,使得Action里面不需要再直接去引用和使用HttpServletRequest与HttpServletResponse等接口。因而使得Action的单元测试更加简单,而且强大的类型转换也使得我们少做了很多重复的工作。
在visual studio当中新建一个ASP.NET MVC web应用程序,
新建完成之后,创建的项目当中即有controllers,models和views,体现了MVC的编程思想。
视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
2.重用性高
MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码,因为多个视图能共享一个模型,它包括任何WEB(HTTP)浏览器或者无线浏览器(wap),比如,用户可以通过电脑也可通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。
3.部署快,生命周期成本低
MVC使开发和维护用户接口的技术含量降低。使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中精力于表现形式上。
4.可维护性高
分离视图层和业务逻辑层也使得WEB应用更易于维护和修改。
MVC的缺点:
1.完全理解MVC比较复杂。
由于MVC模式提出的时间不长,加上同学们的实践经验不足,所以完全理解并掌握MVC不是一个很容易的过程。
2.调试困难。
因为模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难,每个构件在使用之前都需要经过彻底的测试。
3.不适合小型,中等规模的应用程序
在一个中小型的应用程序中,强制性的使用MVC进行开发,往往会花费大量时间,并且不能体现MVC的优势,同时会使开发变得繁琐。
4.增加系统结构和实现的复杂性
对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
5.视图与控制器间的过于紧密的连接并且降低了视图对模型数据的访问
视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。