MVC的发展与应用总结

1、 最初的程序都是是命令行界面,后来进化到GUI(Graphic User Interface),即图形化用户接口。以一个计算器软件为例,一个程序无论C/S还是B/S结构都需要搞定:

  a)       界面布局。整个计算器界面要怎么布局看起来才合理、美观。

  b)       业务逻辑。例如用户点击“=”按钮时,根据输入计算输出结果。

  c)        界面交互。例如用户点击“=“按钮后,界面有什么响应,如显示结果以及结果显示位置等。

  无MVC的情况,如winform在一个Form中,即有计算器的界面显示代码,也有触发监听器后的流程控制逻辑,还有功能逻辑计算代码,这三者搅合在一起,程序复杂了后,代码长度惊人,修改、扩展、阅读他人代码都是问题。

 

2、 桌面GUI程序的MVC设计模式。

  符合“低耦合,高内聚“的软件工程理念。表现在哪里?在于MVC将界面显示代码跟业务逻辑代码有效隔离,将原先糅杂一起的代码分开,各部分趋于专门化,功能职责单一。这样让程序更易阅读、维护、扩展了。

  

  a)       View:负责界面显示。

  b)       Controller:负责View、Model、Service之间的交互、控制业务流程。不涉及具体的业务功能代码。在桌面端Controller可以是组件监听器的匿名实现类。

  c)        Model:简单的数据模型,封装View中的数据,以便于在其他层中的传递和使用(以对象的形式)。是数据模型,并不是业务模型,也不涉及具体的业务功能代码。

  d)       Service:封装了业务逻辑,专门实现业务功能的,如程序功能实现、数据库操作、第三方库调用等。在这里专门把Service标注出来,是为了强调Model仅仅是数据模型,Controller是流程控制,他们都不含业务功能代码,业务功能代码集中在Service层。

 

  桌面MVC的实现。MVC把界面显示集中在View层,功能实现放在Service层,再在他们间封装出Model以便数据共享,和Controller层调和各层的交互及流程控制。这样,就实现了显示与业务的分离。

  

  1)       View与Model应用观察者设计模式,一方面View从Model中获取数据渲染后呈现给用户,另一方面当Model被修改后能自动刷新到View中并显示出来。

  2)       View与Controller可以应用策咯模式,增加程序灵活性。

  3)       Controller组合Service(面向接口)和Model。

 

                        一个java Swing使用MVC的例子:

public abstract class View{

         public void update();

}

public class ViewImpl extends View{

         //View的界面元素属性。

         Model model;//应用观察者模式

         Controller controller;//组合,可以用策略模式

        

         public ViewImpl(){

                  model = new ModelImpl(this);

                  controller = new Controller(model)

                  //界面布局方法调用,初始化组件方法调用(用model中数据)

         }

 

         xxx.addActionListener(new actionlistener{

                  @Override

                  public void actionPerform(){

                          //将界面组件数据刷新到model中

                          controller.do1();

                  }

         })

 

         @Override

         public void update(){

                  //更新model中的数据到View的界面组件中。

         }

        

}

 

 

public interface Controller{

         public void do1();

         public void do2();

         public void do3();

}

public class ControllerImpl implements Controler{

Model model;

         public Controler(Model m){

model = m;

         }

         @Override

         public void do1(){

                  //从model对象获取数据

                  //执行业务逻辑和流程

                  //结果更新到model

                  ////其他一些功能调用和流程控制。

                  model.notifyView();

         }

}

 

 

public interface Model{

         public void notifyView();        

}

public class ModelImpl{

         //模型属性等

         View view;

         public ModelImp(View v){

                  view = v;

         }

         public void notifyView(){

                  view.update();

         }

}

 

 

public class Application{

         public static void main(String[] args){

                  //用户登陆及验证通过后

                  View viewImpl = new ViewImpl();

                  view.visable=true; 

         }

}

 

 

 

         目录结构:这样,1)符合面向接口编程(Controller和Model)和面向抽象编程(View),将设计与实现分离。2)每一个Form都由View、Controller、Model三个文件组成,功能划分清晰,职责单一,便于开发维护。

         |-Form

                  |-View.java

                  |-Controller.java

                  |-Model.java

                  |-ViewImpl_1

                          |-ViewImpl.java

                          |-ControllerImpl.java

                          |-ModelImpl.java

                  |-ViewImpl_2

                  |-ViewImpl_3

         |-Service

         |-Dao

                  |-DBUtilies.java

                  |-UserDao.java

                  |-Impl

                          |-UserDaoImpl.java

                  |-entity

                          |-user.java

         思考:MVC只是一个设计思想,实现方式多样。

         1)上面这种方式,每一个页面从原来的糅合一起到划分成三个页面,让职责单一,便于开发维护。但很明显额外多出很多文件出来,当程序规模不大时是否还要这样一分为三?   2)上面View与Controller,Controller与Model他们之间是组合关系,是否可用策略模式,让View根据不同情况使用不同Controller?

         3)上面通过View的监听器的作用只是调用Controller,真正的流程控制、功能调用在Controler中实现,可不可以直接用监听器的匿名实现类做Controller,而减少额外的Controller文件?那么考虑用Controller类做监听器的实现类又如何呢?

         4)创建对象的方式,是否考虑工厂设计模式,进一步解耦?还有可见性的问题,Controller只可见Model和Service,那要控制View的状态怎么办,是否需要封装其他工具类?这些问题用Spring Ioc解决怎么样?还有dao模块用Mybatis怎么样?

         5)Controller中既要处理功能调用又要处理页面交互,一般可以单线程,先控制功能调用,调用后把结果存到Model,最后控制View显示界面和model数据。可不可以多线程,可不可以把功能调用和页面交互异步处理?那又是否需要同步呢?

 

 

 

3、 web端程序的MVC模式。

  后来B/S结构的程序开始慢慢发展,从静态网页到动态网页。先说不使用MVC设计模式的情况,如java ee中,仅用jsp做开发。那么一个jsp页面中即有html、css、js组成的可视化界面显示,还有流程控制代码,以及访问数据库等的java程序片。为了解决开发的复杂性,同样在B/S中使用MVC设计模式。

  

              (典型的jsp+servlet+javaBean实现MVC)

 

         web的MVC模式与桌面端MVC原理一样,不过在实现上有很大不同,特别是Model层了。两者的Model层在功能上是一样的,都是简单的封装对象。

实现上,前面说过桌面端View与Model是观察者模式,View从Model中获取数据渲染后呈现给用户,同时当Model被修改后能自动刷新到View中并显示出来。而web端MVC中是依赖容器对javaBean组件的支持。jsp和Servlet中按规则使用javaBean,web容器提供一致性支持,servlet修改javaBean的属性后,当响应用户jsp页面时,从javaBean组件中渲染数据到页面并翻译成html返回。

有两个问题:1)、javaBean的使用方式。直接使用,jsp页面用<jsp:UseBean />标签,servlet用new操作符。间接使用,还可以通过内置对象Request等传输。这两种方式依然归于上面Model,因为它的本质没变。

                      2)、从本文开始到现在,我还是认为MVC中的Model只是简单的数据模型,而不是有的博客上说的jsp做界面,servlet做流程控制,javaBean处理业务逻辑。MVC本质上是为了解耦界面显示(如jsp)与业务逻辑(如service),独立出Controller控制流程和各层的交互,再添一个Model层解耦View和Controller。

 

4、 其他MVC开发框架SpringMVC

  上面javaEE原生组件jsp+serlet+javaBean已经可以用MVC模式开发web程序。那为什么大多后台开发都用SpringMVC、Struts2这些开发框架呢?  

  

 

  1) javaEE原生组件虽然对程序开发提供了支持,但面对现在多变的需求,开发过程繁杂,重复代码多。而SpringMVC等提供了封装更好的组件与环境支持,能更快、更简洁用于程序开发。从上面明显看出,组件间耦合性更低了。特别是通过springMVC把View层和其他层分离,让程序真正前后端分离了。

  2) springMVC框架提供了更灵活的程序架构,更适应现在程序开发的多变。如不止可以响应用户jsp页面,还可以返回json、xml、excel、pdf等。

  3) SpringMVC框架,还可以自由地选择与其他框架搭配整合,如spring、mybatis等,对程序的开发提供更好的支持。

  4) 框架本身,支持为特定程序架构定制组件,程序设计将有更多可能。如根据框架提供的接口,用户可以自定义HanderAdapter、ViewResolver等组件,以此为Controller、View的变化提供支持。

 

5、 MVC的衍生------MVP模式

  

 

 

  MVC有效的降低了界面显示层与业务逻辑层的耦合性,准确的说是web端的MVC模式,对于桌面端来说,MVC实现起来有点复杂,View同时依赖Controller和Model,特别是View-Model用观察者模式实现了。MVP由MVC演变而来,但还是有很大区别:

  1) view更新方式不同。MVC中是通过策咯模式,由Model调用View的接口刷新,因此View就要依赖Model。MVP中View只依赖Presenter,由Presenter调用View的接口刷新。

  2) MVC的Model是数据模型,只是简单的数据封装。而MVP中的Model是业务模型。此Model非彼Model,这点是最让人迷糊的了,但要分清,所以上图用Model(service)。

 

6、  MVC的衍生------MVVM模式

  

  

  MVVP同样由MVC演化而来,MVVM与MVP有点类似,不过View的刷新是通过“数据绑定”。很典型的一种实现:前端js框架VUE:

    

 

  1) 通过事件驱动,把显示层大的用户操作传递到js逻辑层

  2) js执行逻辑处理后,修改data域

  3) data域和显示层html是绑定了的,所以自动把结果刷新到显示层html

 

7、 总结

  不论桌面端还是web端,一次程序交互可以抽象为:

    

    

  1)请求:桌面端通过事件监听提交;web前端通过事件驱动提交给js逻辑层;后端通过http、https、web service等协议接受。

  2)处理:控制器调用接口处理业务逻辑,以及整个操作流程的统筹控制。

  3)响应:响应内容包括页面和数据,有可能只有页面如静态网页,也有可能只有数据如json。

 

  各种模式主要区别从上面第3步总结——响应:

            桌面端MVC,是用观察者模式实现,由Model调用View的接口刷新界面。

            web端MVC,是通过web容器、SpringMVC等三方库的支持,将Modle渲染到View再返回给用户显示。

            MVP模式,多用于桌面端或安卓等开发,由Presenter调用View的接口刷新界面。

            MVVM模式,多用于web前端开发,通过数据绑定刷新页面数据。

posted @ 2018-04-01 23:06  衿沫青冥  阅读(297)  评论(0编辑  收藏  举报