为什么MVC不是一种设计模式? ---比较Backbone和Ext4.x在MVC实现上的差异

2024-04-21 12:38

本文主要是介绍为什么MVC不是一种设计模式? ---比较Backbone和Ext4.x在MVC实现上的差异,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

为什么MVC不是一种设计模式?

 

---比较Backbone和Ext4.x在MVC实现上的差异


转载:http://damoqiongqiu.iteye.com/blog/1949256

 

大漠穷秋

 

前言

 

圣人云:不想做妈咪的小姐不是好码农。

 

每一个码农的心中都有一个终极理想,那就是有一天不用再Coding。

 

在成为妈咪的道路上,“设计模式”被认为是一项必备的技能。

 

因此,经常有湿主会问小僧这样一个问题:为什么MVC不是一种设计模式呢?

 

对于这样naive的问题,小僧向来是嗤之以鼻的,你们啊!图样图森破!

 

机缘巧合,前段时间在焦点技术大会上听到一位大牛关于Backbone的介绍,于是小僧最近一段时间研究了一下Backbone相关的内容。

 

在《Developing Backbone Application》(戳这里查看此书电子版)这本书上,恰好有几段关于MVC相关的内容,看完这段内容之后,小僧突然有醍醐灌顶之感。原来为什么MVC不是一种设计模式这个问题还真的是个问题,看起来是小僧自己执念太重了!

 

罪过罪过。

 

弥陀佛~~!

 

(淘宝的一位牛人白汀 @白汀UX 翻译了《Developing Backbone Application》这本书,完整的在线电子版请戳这里,小僧友情建议一下这位大牛,请注意翻译质量,错别字和语句不通顺的问题太多了点!)

 

为了让各位道友也能领悟到设计模式里面的一些奥妙,小僧特作此文。

 

稍安勿躁,让小僧给各位湿主解说一番。

 

(这里就不对着原文翻译了,为了方便各位道友理解,小僧总结一下其中的精髓,E文好的请点浏览器右上角。)

 

MVC的起源

 

1979年,Trygve Reenskaug 这位牛人在Smalltalk-80系统上首次提出了MVC的概念,最初的时候叫做Model-View-Controller-Editor。

 

(我擦,1979年小僧还在佛祖那儿念经呢吧?)

 

1994年,Gof(Gang of Four)在《Design Patterns: Elements of Reusable Object-Oriented Software》一书中对MVC模式做了深入的解析。

 

Trygve Reenskaug最初提出MVC的目的是为了把数据(Model)视图(View)分离开来,然后用控制器(Controller)作胶水来粘合M和V之间的关系。

 

很显然,这样做的目的是为了实现注意点分离这样一个更高层次的设计理念,也就是让专业的对象做专业的事情,View就只负责视图相关的东西,Model就只负责描述数据模型,Controller负责总控,各自协作,别总掺和到一起乱成一锅粥!

 

最古典的MVC实现

 

请注意上一小节中的两个年份,1979年,计算机还不是屌丝能玩儿得起的东西!那时候比尔盖茨还是个小学生,并且他还没有辍学创办MicroSoft,那时候人们不知道什么是Windows,当然,也没有什么GUI的概念。

 

各位道友可以想想一下,黑黑的命令行,一串一串的文本字符...

 

嗯嗯,就是那个样子的!

 

显然,在这样的历史背景之下,原始的MVC模式显然不是如今所理解的那种样子。

 

在Smalltalk-80上的那个古典实现上,View和Controller都是要监听Model的,也就是说,只要数据发生变化,视图和控制器都会收到通知的!

 

也就是这个样子的:

 



 

 

C和M,V和M之间都是通过Observer pattern (观察者模式)来实现的。

 

对于这种古典的实现细节,请参见Martin Fowler的这篇文章。

 

为什么GOF的23种设计模式里面没有MVC?

 

好了,到这里应该来解释为什么MVC不是一种设计模式这个问题了。

 

对于这个问题,直接引用@白汀UX 的译文如下:

 

GoF (Gang of Four,四人组, 《Design Patterns: Elements of Reusable Object-Oriented Software》/《设计模式》一书的作者:Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides)并没有把MVC提及为一种设计模式,而是把它当做“一组用于构建用户界面的类集合”。在他们看来,它其实是其它三个经典的设计模式的演变:观察者模式(Observer)(Pub/Sub), 策略模式(Strategy)和组合模式(Composite)。根据MVC在框架中的实现不同可能还会用到工厂模式(Factory)和装饰器(Decorator)模式。我在另一本免费的书“JavaScript Design Patterns For Beginners”中讲述了这些模式,如果你有兴趣可以信息。

正如我们所讨论的,models表示应用的数据,而views处理屏幕上展现给用户的内容。为此,MVC在核心通讯上基于推送/订阅模型(惊讶的是 在很多关于MVC的文章中并没有提及到)。当一个model变化时它对应用其它模块发出更新通知(“publishes”),订阅者 (subscriber)——通常是一个Controller,然后更新对应的view。观察者——这种自然的观察关系促进了多个view关联到同一个 model。

对于感兴趣的开发人员想更多的了解解耦性的MVC(根据不同的实现),这种模式的目标之一就是在一个主题和它的观察者之间建立一对多的关系。当这个 主题改变的时候,它的观察者也会得到更新。Views和controllers的关系稍微有点不同。Controllers帮助views对不同用户的输 入做不同的响应,是一个非常好的策略模式列子。

 

嗯嗯,知道为什么MVC没有被GOF当作【一种】模式来对待了吧?

 

因为它实际上是三种模式的合体

 

(如果以后有人问你这个问题,你可以直接引述上面这段话,绝对高端大气上档次!一下就能把TA给震住!)

 

前端MVC与经典MVC的差异

 

正如前文所述,在当初提出MVC这种设计理念的历史条件之下,基本上还没有图形界面,当然像JavaScript这种东西也是不存在的!

 

但是,如今不同了!在如今前端框架(尤其是各种JavaScript框架)大爆炸的背景下,几乎所有的框架都会号称自己具有MVC的特性。

 

但是,有一点请注意,如今的MVC实现与古典的MVC实现方式已经大不相同了。

 

下面拿Backbone和Ext来举两个例子。

 

Backbone中的MVC实现方式

 

对于最新版本的Backbone来说,它不再区分出独立的Controller,它的控制器代码与View是写在一起的,仅仅明确区分出了Model的概念,举个栗子:

 




 
 

 

呃,请不要在意那些细节,看红框的部分即可。

 

第一处,显然Employee是一个Model;

 

第二处和第三处,显然那EmployeeView是一个View;

 

第四处,setText这个方法显然是充当Controller的角色。

 

很显然,在Backbone的这种实现之下,View和Controller合体了,并没有抽象出独立的Controller这种东西。

 

显然,这是古典MVC的一个变种,也就是原书作者所谓的MV*。

 

各位道友请仔细想想,Backbone的这种做法有没有道理?

 

Ext4.x中的MVC实现

 

再来看Ext4.x中的MVC实现。 




 
 

 

从以上示例项目截图(controller/model/view等目录)可以看出来(此图来自Ext官方的说明文档),Ext4.x采用了古典的MVC设计方案,它明确地抽象出了Controller这个类

 

为什么小僧坚持认为Ext4里面的MVC是一种过度设计?

 

熟悉Ext历代版本的道友会知道,在Ext4.x之前,并没有做出前面这样的区分。

 

【以下纯属个人看法,仅供参考】

 

与Backbone相比,Ext4.x的这个设计纯属鸡肋,实际上,对于带有GUI界面的代码来说,Controller是无法独立于View而存在的。

 

因为,在Controller里面一定需要到处访问View中的内容,Controller是无法独善其身的!

 

Ext4.x的这个实现为了MVC而MVC的一个绝佳例子。

 

在Ext4.x中,类似为了模式而模式的例子不胜枚举,据小僧不怀好意的推测,这一定是Jack离开之后这帮人乱搞的结果。

 

这也是为什么Ext4.x的运行效率如此之差的原因,之一。

 

小僧都替你们捉急有木有?!!!

 

对于4.x的效率问题,网上的吐槽不计其数,各位道友可自行咨询度娘。

 

为什么小僧认为MVP/MV*才是最佳设计理念

 

这里请区分好概念,设计理念具体实现方式不是一回事。

 

在关于Backbone的这本书中,作者还提出了MV*和MVP (Model-View-Presenter) 的说法,不得不说,这是非常具有洞察力的见解。

 

其中的Presenter可以用来与服务端交互,获得Model数据,以及把Model提交到服务端等等。

 

在当前MVC很多的实现里面,与服务端的交互是写在Model里面的(Backbone和Ext都是这样)。

 




 
 

 

小僧认为,这种实现方式有待商榷,如果在Model里面含有后台交互的代码,在不同的场景下显然无法达到复用Model的目的。

 

比如,在场景一下面你希望数据模型访问 myApp/delUser.action,而在场景二下面你希望它访问 myApp/daddUser.action,这种情况你就麻烦了不是?

 

而且,与后台的交互过程应该抽象成独立的数据传输层,在这一点上Ext的实现略好。

 

因此,MV*、MVVM、MVP都可以看作MVC的现代衍生版,M和V一定要明确区分,至于要不要抽象出其它类,其它类是应该和M合体还是应该和V合体,各位道友看着办即可!

 

结语

 

当初提出MVC,是为了实现关注点分离这样一种设计理念,MVC只是实现这一理念的一种方式而已。因此,不必拘泥于一定要抽象出Model/View/Controller这样的类结构。

 

学习模式!运用模式!超越模式!

 

心中无码,一切都无码!

 

弥陀佛~~!

 

(请理性吐槽,否则回头小僧到佛祖那儿说你坏话,哼!)

这篇关于为什么MVC不是一种设计模式? ---比较Backbone和Ext4.x在MVC实现上的差异的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/923109

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2