MVC架构详解
1 什么是MVC?
MVC即model-view-controller的缩写,他是实现数据显示与控制逻辑分离的框架,具有明显的分层结构,每一层的职责清晰明确,层次之间交互用较好的规范约束。Model层负责数据的封装,不夹杂任何逻辑控制,不考虑展现形式,代码干净利落;View层负责数据展示,同样不包含逻辑控制,但是界面的代码实现会受Model层约束,不同的model可能需要不同的view展现,同时view还需要响应model数据的更新;Controller层稍微复杂点,是整个架构中的核心,负责整个框架的运转,他的功能就类似电脑的CPU,负责数据的调度与逻辑运算,控制着数据的加工及如何展示。
2 对MVC的误解
许多人在谈论MVC时,都说MVC是一种设计模式,更有甚者说MVC是B/S系统中特有的设计模式,其实不然,MVC是由许多模式组合起来的系统架构,不能与设计模式混为一谈,其最早源于一门比较早的面向对象语言Smalltalk中的C/S系统的设计,java中的Swing也采用这种框架设计的,不过随着互联网的兴起,MVC逐渐在B/S系统中大行其道,现在几乎所有的B/S都采用MVC或者采用一种扩展后的MVC。
3 MVC剖析
View会注册多个controller,这些controller处理不同的用户请求;View通常绑定一个model,但model不局限于被一个view绑定,当model数据变化时,会发送消息通知相关的view更新,整个流程比较清晰简单,但是每一层即层次之间交互都采用了用适当的设计模式。接下来我们一一剖析。
首先是View层,view’负责展示数据模型,你可能觉得view应该很简单,谈不上什么设计模式,但是别忘了,View是有model决定的,而model数据是多种多样的,我们没有办法也不可能设计一个view就能展示所有的model,往往需要设计许多简单的、小型的原子view,然后将这些view组合起来,形成一个完整的用户界面。为了便于区分,我们将原子View称作Vfp(view for programer),把组合View称作Vfu(View for user),每一个Vfp都能显示一定的数据并响应用户的操作,但是单独的Vfp没有意义,每一个Vfu不关注它内部的Vfp的细节,我们可以像使用Vfp一样使用Vfu,这就是典型的Composite模式,这种模式能简化View设计,我们通过组合不同的Vfp就能设计出任意复杂的Vfu,这种模式在C/S系统中大量的采用,例如,我的任何界面都是利用原子控件进行组合设计,而我们也可以设计一些原子控件,提高代码的复用性,但是B/S系统中,我们的界面是有html来编写的,虽然html界面本身也是依赖原子的div/hr/table等标签组成,但是html不具备引用其他html的能力,我们没法针对一些相似的功能,编写一套view,然后在需要的地方引用,所以B/S界面的View层复用率都很低,不过这种问题在J2EE开发中,sun提高了一套不错的解决方案,采用Taglib来实现界面的复用和组合。
其次是Controller层,该层的作用就是响应并处理某种请求,这些请求通常来自view层,简单来说就是一种事件处理器,如C/S中的各种action/listener,不同的事件需要不同的处理方式,controller通常有一个分类的层次结构,如鼠标事件的Mosuelistener,键盘事件的KeyListener,这些Action/listener是对某种功能的抽象,具体的功能实现由编程时实际传入的对象完成,这就是典型的S t r a t e g y模式,下面我们来分析一些具体的例子:
在java Swing中,几乎所有的view都支持鼠标事件,Swing把这种功能抽象为一MouseListener
不同的view要支持这种功能只需要注册一个实现MouseListener对象即可,我们可以很方便支持或屏蔽某种功能,假释我们有个JLabel,需要支持鼠标双击,但是不需要响应鼠标移动,我们可以这样编码:
JLabel jl = new JLabel(); jl.addMouseListener(new MouseListener() { @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseClicked(MouseEvent e) { if(e.getClickCount()==2) { //doSomeThing } } });
最后是Model层,model层通过一种订阅/通知的方式实现模型和视图的解耦,这样我们的视图和模型就可以单独开发,单独测试,当模型数据发生变化时,他会通知相关的视图,视图进行刷新,这样,你可以为一个模型提供不同的多个视图表现形式,也能够为
一个模型创建新的视图而无须重写模型。 这是典型的观察者模式的应用。
4 MVC的发展
MVC是源于C/S系统,但随着他在B/S系统中的大量使用,现在已经由3层架构演化为多层架构,典型的,增加了一个DAO层负责数据库处理,controller收到请求后调用DAO获取或修改数据。一些框架很好的实现了MVC架构,如Spring structs等,这使得我们从一些基础的设计中解脱出来,用更多的精力去关注业务处理。