从MVC框架看MVC架构的设计

从MVC框架看MVC架构的设计尽管MVC早已不是什么新鲜话题了,但是从近些年一些优秀MVC框架的设计上,我们还是会发现MVC在架构设计上的一些新亮点。本文将对传统MVC架构中的一些弊病进行解读,了解一些优秀MVC框架是如何化解这些问题的,揭示其中所折射出的设计思想与设计理念。MVC回顾作为一种经典到不能再经典的架构模式,MVC的成功有其必然的道理,这个道理不同的人会有不同的解读,笔者最认同的一种观

大家好,又见面了,我是你们的朋友全栈君。

推荐:博主历时三年倾注大量心血创作的大数据平台架构与原型实现:数据中台建设实战一书已由知名IT图书品牌电子工业出版社博文视点出版发行,真诚推荐给每一位读者!点击重磅推荐:建大数据平台太难了!给我发个工程原型吧!了解图书详情,扫码进入京东手机购书页面!

从MVC框架看MVC架构的设计

 

从MVC框架看MVC架构的设计

尽管MVC早已不是什么新鲜话题了,但是从近些年一些优秀MVC框架的设计上,我们还是会发现MVC在架构设计上的一些新亮点。本文将对传统MVC架构中的一些弊病进行解读,了解一些优秀MVC框架是如何化解这些问题的,揭示其中所折射出的设计思想与设计理念。

MVC回顾

作为一种经典到不能再经典的架构模式,MVC的成功有其必然的道理,这个道理不同的人会有不同的解读,笔者最认同的一种观点是:通过把职责、性质相近的成分归结在一起,不相近的进行隔离,MVC将系统分解为模型、视图、控制器三部分,每一部分都相对独立,职责单一,在实现过程中可以专注于自身的核心逻辑。MVC是对系统复杂性的一种合理的梳理与切分,它的思想实质就是“关注点分离”。至于MVC三元素的职责划分与相互关系,这里不再赘述,下图给出了非常细致的说明。

 

从MVC框架看MVC架构的设计

图1:MVC组件的功能和关系[i]

View与Controller的解耦:mediator+二次事件委派

笔者早年开发基于swing的GUI应用时,在架构MVC的实践过程中深刻体会到了view与controller之间的紧密耦合问题。在很多事件驱动的GUI框架里,如swing,用户对view的任何操作都会触发一个事件,然后在listener的响应方法里进行处理。如果让view自己注册成为事件的listener,则必须要在view中加入对controller的引用,这不是MVC希望看到的,因为这样view和controller就形成了紧密的耦合关系。若将controller注册为listener,则事件响应将由controller承担,这又会导致controller处理其不该涉及的展现逻辑,造成view和controller难以解耦的原因在于:多数的用户请求都包含一定成分的展现逻辑和一定成分的业务逻辑,两种逻辑揉合在一个请求里,在处理的时候,view与controller很难合理地分工。解决这一问题的关键是要在view与controller之间建立一种可以将展现逻辑与业务逻辑进行有效分割的机制,在这方面,PureMVC[ii]的设计非常值得参考,它通过引入mediator+二次事件委派机制很好的解决了view与controller之间的紧耦合问题。

Mediator是一种设计模式,这种模式在组件化的图形界面框架中似乎有着普遍的应用场景,即使是在四人帮的《设计模式》一书中,也使用了一个图形界面程序的示例来讲解mediator。mediator的设计用意在于通过一个媒介对象,完成一组对象的交互,避免对象间相互引用,产生复杂的依赖关系。mediator应用于图形界面程序时,往往作为一组关系紧密的图形组件的交互媒介,完成组件间的协调工作(比如点选某一按钮,其他组件将不可用)。在PureMVC中,mediator被广泛应用,其定位也发生了微妙的变化,它不再只是图形组件间的媒介,同时也成为了图形组件与command之间的媒介,这使得它不再是可选的,而是成为了架构中的必需设施。对应到传统MVC架构中,mediator就是view与controller之间的媒介(当然,也依然是view之间的媒介),所有从view发出的用户请求都经过了mediator再传递给controller,它的出现在一定程度上缓解了view与controller的紧密耦合问题。

当view、mediator和controller三者被定义出来,并进行了清晰的职责划分后,剩下的问题就是如何将它们串联起来,以完成一个用户请求了,在这方面,事件机制起到了至关重要的作用。事件机制可以让当前对象专注于处理其职责范围内的事务,而不必关心超出部分由谁来处理以及怎样处理,当前对象只需要广播一个事件,就会有对此事件感兴趣的其他对象出来接手下一步的工作,当前对象与接手对象之间不存在直接依赖,甚至感知不到彼此的存在,这是事件机制被普遍认为是一种松耦合机制的重要原因。讲到这里插一句题外话,在领域驱动设计(Domain-Driven Design)里,著名的Domain Event模式也是有赖于事件机制的这一特性被创造出来的,其用意正是为了保证领域模型的纯净,避免领域模型对repository和service的直接依赖。回到PureMVC, 我们来看在处理用户请求的过程中,事件机制是如何串联view、mediator和controller的。在PureMVC里,当一个用户请求下达时,图形组件先在自身的事件响应方法中实现与自身相关的展现逻辑,然后收集数据,将数据置入一个新的event中,将其广播出去,这是第一次事件委派。这个event会被一个mediator监听到,如果处理该请求需要其他图形组件的协助,mediator会协调它们处理应由它们承担的展现逻辑,然后mediator再次发送一个event(这次的event在PureMVC里称之为notification),这个event会促使某个command执行,完成业务逻辑的计算,这是第二次事件委派。在两次事件委派中,第一次事件委派让当事图形组件完成“处理其职责范围内的展现逻辑”后,得以轻松“脱身”,免于被“协调其他图件处理剩余展现逻辑”和“选择并委派业务对象处理业务逻辑”所拖累。而“协调其他图形组件处理剩余展现逻辑”显然是mediator的职责,于是第一次广播的事件被委派给了mediator. mediator在完成图形组件的协调工作后,并不会插手“选择并委派业务对象处理业务逻辑”的工作,这不是它的职责,因此,第二次事件委派发生了,一个新的event由mediator广播出去,后被某个command响应到,由command完成了最后的工作——“选择并委派业务对象处理业务逻辑”。

从MVC框架看MVC架构的设计

图2:mediator+二次事件委派机制

总结起来,PureMVC是通过在view与controller之间引入mediator,让view与controller变成间接依赖,用户请求从view到mediator,再从mediator到controller均以事件方式委派,mediator+二次事件委派的组合可以说是一种“强力”的解耦机制,它实现了view与controller之间的完全解耦。

从Controller到Command,自然粒度的回归

目前,很多平台的主流MVC框架在设计上都引入了command模式,command模式的引入改变了传统MVC框架的结构,受冲击最大的就是controller。在过去传统的MVC架构里,一个controller可能有多个方法,每个方法往往对应一个user action,因此,一个 controller往往对应多个user action,而在基于command的MVC架构里,一个command往往只对应一个user action。传统MVC架构里将一个user action委派到某个controller的某个方法的过程,在基于command的MVC架构里变成了将useraction与command一一绑定的过程。如果说传统controller的管理方式是在user action与model之间建立“集中式”的映射,那么基于command的管理方式就是在user action与model之间建立“点对点式”的直连映射。

从MVC框架看MVC架构的设计

图3:从基于Controller到基于Command的架构演进

主流MVC框架向command转型是有原因的,除了command自身的优势之外,一个非常重要的原因就是:由于缺少合理的组织依据,controller的粒度很难拿捏。controller不同于view与model,view与model都有各自天然的粒度组织依据,view的组织粒度直接承袭用户界面设计,model的组织粒度则是依据某种分析设计思想(如OOA/D)进行领域建模的结果,controller需要同时协调view与model,但是view与model的组织结构和粒度都是不对等的,这就使得controller面临一个“在多大视图范围内沟通与协调多少领域对象”的问题,由于找不出合理的组织依据,设计者在设计controller时往往感到无所适从。相比之下,command则完全没有controller的困惑,因为command有一个天然的组织依据,这就是user action。针对一个user action设计一个command,然后将两者映射在一起,是一件非常自然而简单的事情。不过,需要说明的是这并不意味着所有command的粒度是一样的,因为不同的user action所代表的业务量是不同的,因此也决定了command是有“大”有“小”的。遵循良好的设计原则,对某些较“大”的command进行分解,从中抽离出一些可复用的部分封装成一些较“小”的command是值得推荐的。很多MVC框架就定义了一些相关的接口和抽象类用于支持基于组合模式的命令拼装。

不管是基于controller还是基于command,MVC架构中界定的“协调view与model交互”的控制器职责是不会变的,都需要相应的组件和机制去承载与实现。在基于command的架构里,command承担了过去controller的部分职责,从某种意义上说 command是一种细粒度的controller,但是command的特性是偏“被动”的。一方面,它对于view和model的控制力比controller弱化了很多, 比如,一般情况下command是不会直接操纵view的。另一方面,它不知道自己与什么样的user action映射在了一起,也不知道自己会在何种情况下被触发执行。支撑command的运行需要额外的注册、绑定和触发机制,是这些机制加上command一起实现了controller的职责。由于现在多数基于command的MVC框架都实现并封装了这些重要的机制,所以从某种意义上说,是这些框架自身扮演了controller角色。

小结

本文主要分析了过去传统MVC架构中存在的两大弊病:view与controller的紧密耦合以及controller粒度难以把控的问题,介绍了一些MVC框架是如何应对这些问题的,这些设计方案所体现出的优秀设计思想是非常值得学习的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126204.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • maven中jar和war的区别

    maven中jar和war的区别jar文件包括java普通类、资源文件和普通文件,在maven中即是打包src/main/java和src/main/resources资源文件夹下的所有文件。在打包的时候会自动生成MATA-INF文件夹,用于存储maven的pom信息和MANIFEST.MF文件。例如:war文件包含全部的web应用程序,即所有的java类,配置信息和jsp、js等静态资源。但是需要注意war

    2022年5月23日
    79
  • 基于matlab的图像处理案例教程_matlab gui图像处理

    基于matlab的图像处理案例教程_matlab gui图像处理一、imfinfo函数——查看图像文件信息,注意参数是文件路径和文件名,不是图像对应的矩阵。imfinfo(‘C:\Users\zhulf\Desktop\1.jpg’)ans=Filename:’C:\Users\zhulf\Desktop\1.jpg’FileModDate:’19-Apr-201508:40:54′

    2022年10月4日
    2
  • 挖矿程序的处理方式及步骤

    挖矿程序的处理方式及步骤概述随着币圈市场交易的活跃,币价也被日益推高。从BTC兑美元的在线交易平台上可以看出,BTC的价格屡创新高,这与MG的2W亿脱不了干系。“重赏之下,必有勇夫”,在互联网圈里也同样适用啊。所以服务器被植入挖矿程序已经不是很稀奇的事情了,很多服务器因为漏洞、弱密码、禁用防火墙等等举措,而被做了提权后,置入了挖矿程序。如果你接收到阿里云类似于挖矿程序的报警,那就不要慌。借用一句话就是:“遇事不要慌,先拍照,发个朋友圈”。挖矿程序的处理方式以下,简单地说一下遇到挖矿…

    2022年6月25日
    42
  • 几种web字体格式建议收藏

    目前,文字信息仍是网站最主要的内容,随着CSS3技术的不断成熟,Web字体逐渐成为话题,这项让未来Web更加丰富多彩的技术拥有多种实现方案,其中之一是通过@font-face属性在网页中嵌入自定义字体

    2021年12月20日
    40
  • php开源的客服系统_在线客服源码php

    php开源的客服系统_在线客服源码php在线客服系统软件使开发和运营团队能够高速协作,因此要求源码系统能够快速响应业务变化,并快速提供出色的客户和员工服务体验。  在线客服源码演示及获取:https://gitee.com/wang_li989/kfxt  客服沟通问题加起来会成为重大的财务损失。您的组织快速有效地解决这些问题的能力直接影响到未满足的SLA义务和客户体验,这两个方面对公司的成功至关重要。在线客服系统是企业战略的核心组成部分。通过减少识别和解决问题所需的时间,您的组织可以提高客户忠诚度,最大限度地延长正常运行时间,并提供始终如

    2022年4月19日
    52
  • 基于单片机的交通信号灯控制系统设计论文_交通信号灯控制设计

    基于单片机的交通信号灯控制系统设计论文_交通信号灯控制设计本系统采用STC89C51单片机以及单片机最小系统和74HC245驱动电路以及外围的按键和数码管显示等部件,设计一个基于单片机的交通灯设计。设计通过两位一体共阴极数码管显…

    2022年9月24日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号