MVC和三层架构

一、缘起

最近参加了一些开发技术上的面试,不少应聘者都声称“精通基于MVC设计模式的三层架构”。 这种提法意味着,MVC是三层架构的一种实现方式。

面试中还有人提到,使用了“MVC中的EF”。忍不住追问,EF是MVC的组成部分?得到了肯定的回答。

参加面试的也有人将MVC和三层架构对立起来,声称他们的项目使用了MVC,而没有使用多层架构。或者反之。

因此,有必要探究一下:MVC和三层架构之间是什么关系。

二、 MVC是一种设计模式么?

很多人会顺嘴说到“MVC设计模式”,让我们先偏离一下正题,先对这个问题较较真:MVC是不是一种设计模式。

在经典之作《设计模式——可复用面向对象软件的基础》(后文简称GoF)中,讨论了SmallTalk中的MVC:

MVC由三类对象组成:模型、视图和控制器。模型是应用中的对象,视图是模型的屏幕展现,控制器定义了用户界面如何响应用户的输入。在模型和视图间建立订阅/通知机制,MVC实现了对二者的解耦。无论模型的数据什么时候发生变化,都要通知建立在其上的视图,这样视图才能进行更新。我们可以在一个模型上关联多个视图,每个视图可以有不同的表现形式。也可以为模型新建视图,而不必修改模型本身。

图1. MVC的原始定义(该图来自Model View Controller: History, theory and usage,推荐)

SmallTalk中的MVC,其意图在于构建整个应用程序,被称为一种Paradigm。GoF并未将MVC列入23个设计模式中,而是分析了MVC用到了哪些设计模式:策略模式、模板方法模式、装饰器模式等。

鉴于此,不妨将MVC理解为一种应用的架构。其粒度要远远超过设计模式。一个设计模式一般包含2-5个类,MVC则远不止此。实际上,MVC也是讨论应用架构的书中经常讨论的内容,如Martin Flower的《企业应用架构模式》等。

三、 Model 1 vs Model 2

SmallTalk MVC出现于上世纪80年代,对我们现在的很多小伙伴来说,那属于史前时代,因为那时候Web应用还没有踪影。

MVC大行其道,很大程度上应该归功于Web应用的兴起,特别是JSP Model2的实现。

最初,Web应用还较为简单,JSP可以包打天下:将界面展现、逻辑处理集于一身。JSP中既包含页面展现的内容,以HTML为主,也包含逻辑处理的内容,以Java代码为主。这种处理模式称为JSP Model 1。

                                                 图 2 JSP Model 1

后来,随着应用复杂程度的增加,JSP Model 1带来问题越来越多。人们就把JSP的职责独立出来,还原到其原来的定位:页面展现,而将请求处理、数据访问等功能从其中剥离出来。这形成了处理模式Model 2。

                                                                    图 3 JSP Model 2

Model 2将系统中的展现、数据访问和请求处理拆分开来,自然令人想到MVC,因此,Model 2和MVC基本上画上了等号。但Web年代的MVC已经不是最初的MVC,其中最明显的区别是,取消了View对Model的监听,因为在B/S环境下,实现这个得不偿失。

四、 MVC和三层架构

Model 2最为著名的实现是Struts,这是在J2EE世界;在.NET世界中,自然ASP .NET MVC。是的,你没看错,.NET MVC是JSP Model 2在.NET中的实现。

因此,我们考虑MVC就以Structs和.NET MVC为主。

MVC从最初一直到Struts,其意图都在于构建整个应用程序,而三层架构也是用于构建完整的应用。如果将其放在一起,会有什么对应关系呢?

                           图 4 MVC与三层架构的对应关系是怎样的?

我们分别针对Struts和.NET MVC,探究一下这个问号。

4.1 Struts

Struts相当忠实地实现了Model 2。其部件与三层的对应关系,分析如下:

  1. 视图,自然属于展现层;
  2. 控制器。从图 3中可以看出,控制器有三项职责:接受并处理请求,选择并构建视图,创建模型对象并与其交互。前两者可以归于展现层,后一项能力则可以归于业务逻辑层。
  3. 模型。JavaBean和企业服务器/数据源交互,将其归于数据访问层是比较自然的。

这种对应关系可以图示如下:

                        图 5 Struts与三层架构的对应关系

考虑一下在三层架构中,SSH各自的势力范围,这种对应关系可能更为清楚一些:

  1. Struts:定义整个应用架构,但主要贡献在于视图和控制器;
  2. Spring:服务于各层,为实现提供支撑手段。特别是在业务逻辑层,控制器借助IoC等技术实现对模型的控制;
  3. Hibernate:位于数据访问层,定义模型并实现数据访问。

4.2 .NET MVC

从概念上看,JSP Model 2并没有清晰地界定三层架构,特别是对于业务逻辑层刻画很少。由于Struts是对JSP Model 2的忠实实现,这个问题在Struts中同样存在。

事情到了ASP .NET MVC有了些变化。这个变化突出表现在对模型的定义。在.NET MVC中,可以使用标签定义模型属性的展现和验证方式。

例如:

namespace Models

{
    public class Student 
    {
        [DisplayName("联系人")]
        [Required(ErrorMessage = "对不起,联系人姓名不能为空")]
        public string ContactName { get; set; }

 
        [DisplayName("移动电话")]
        [CustomValidation(typeof(StudentModel), "CheckPhoneNumbers")]
        public string MobilePhoneNumber { get; set; }
 

        ……
    }
}


[DisplayName]标签用于创建该属性的标签,[Required]、[CustomValidation]等标签则用于控制对用户输入结果的验证。这些标签属于展现层的功能,加上了这些标签的模型,也就被定位于展现层,而不再适用于数据访问。因此,.NET MVC中的模型,更为准确的名称应当是视图层的模型,即ViewModel,简称VM。

这样,整个.NET MVC的定位也明确了:它属于展现层。

         图 6 ASP .NET MVC与三层架构的对应关系

在产品/工具选型上,则可以借鉴SSH,确定各项在.NET中的替代品。在我们这里的讨论中,Struts的替代品自然是.NET MVC,Spring则可以选择Spring .NET或Enterprise Library,Hibernate的替代品,可以考虑NHibernate或Entity Framework。

五、总结

本文的关注点在于MVC与三层架构之间的关系,对于三层架构自身则较少提及,更没有展开,例如,有的实现中扩展为更多层,我们笼统地称为三层架构。

关于MVC与三层架构之间的关系,可以归纳如下:

  1. 不能混为一谈。两者来源不同,意图都是构造完整的应用,可以看作两个应用架构;
  2. 不能“混为两谈”。两者不是对立的,可以互相融合,使得应用的架构更为清晰。例如用MVC实现三层中的展现层。
  3. MVC偏重于具体的技术和产品,三层架构更多地是一个概念。
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值