Android中常见的MVC/MVP/MVVM模式

Android中常见的MVC/MVP/MVVM模式

经典MVC

在1979年,经典MVC模式被提出。

在当时,人们一直试图将纯粹描述思维中的对象与跟计算机环境打交道的代码隔离开来,而Trygve Reenskaug在跟一些人的讨论中,逐渐剥离出一系列的概念,最初是Thing、Model、View、Editor。后来经过讨论定为Model、View和Controller。作者自言“最难搞的就是给这些架构组件起名字”。

因为当时的软件环境跟现在有很大不同,所以经典MVC中的概念很难被现在的工程师理解。比如经典MVC中说:“view永远不应该知道用户输入,比如鼠标操作和按键。”对一个现代的软件工程师来说,这听上去相当不可思议:难道监听事件不需要类似这样的代码吗?

view.onclick = ......

但是想想在70年代末,80年代初,我们并没有操作系统和消息循环,甚至鼠标的光标都需要我们的UI系统来自行绘制,所以我们面对的应该是类似下面的局面:

mouse.onclick = ......
mouse.onmove = ......

当鼠标点击事件发生后,我们需要通过view的信息将点击事件派发到正确的view来处理。假如我们面对的是鼠标、键盘驱动这样的底层环境,我们就需要一定的机制和系统来统一处理用户输入并且分配给正确的view或者model来处理。这样也就不难理解为什么经典MVC中称"controller是用户和系统之间的链接"。

因为现在的多数环境和UI系统设计思路已经跟1979年完全不同,所以现代一些喜好生搬硬套的"MVC"实现者常常会认为controller的输入来自view,以至于画出model、view、controller之间很奇葩的依赖关系:

我们来看看Trygve Reenskaug自己画的图(这恶趣味的骷髅啊……):

值得一提的是,其实MVC的论文中,还提到了"editor"这个概念。因为没有出现在标题中,所以editor声名不著。MVC论文中推荐controller想要根据输入修改view时,从view中获取一个叫做editor的临时对象,它也是一种特殊的controller,它会完成对view和view相关的model的修改操作。

控件系统

MVC是一种非常有价值的架构思路,然而时代在变迁,随着以windows系为代表的WIMP(window、icon、menu、pointer)风格的应用逐渐成为主流,人们发现,view和controller某些部件之间的局部性实际上强于controller内部的局部性。于是一种叫做控件(control)的预制组件开始出现了。

控件本身带有一定的交互功能,从MVC的视角来看,它既包含view,又包含controller,并且它通过"属性",来把用户输入暴露给model。

controller的输入分配功能,则被操作系统提供的各种机制取代:

  • 指针系统:少数DOS时代过来的程序员应该记得,20年前的程序中的“鼠标箭头”实际上是由各个应用自己绘制的,以MVC的视角来看,这应当属于一个"PointerView"的职责范畴。但是20世纪以后,这样的工作基本由操作系统的底层UI系统来实现了。
  • 文本系统:今天我们几乎不需要再去关心文本编辑、选中、拖拽等逻辑,对web程序员可以尝试自己用canvas写一个文本编辑框来体验一下上个时代程序员编写程序的感受。你会发现,选中、插入/覆盖模式切换、换行、退格、双击、拖拽等逻辑异常复杂,经典MVC模式中通常使用TextView和TextEditor配合来完成这样的工作,但是今天几乎找不到需要我们自己处理这些逻辑的场景。
  • 焦点系统:焦点系统通过响应鼠标、tab键等消息来使得控件获得操作系统级唯一的焦点状态,所有的键盘事件通常仅仅会由拥有焦点的控件来响应。在没有焦点系统的时代,操作系统通常是单任务的,但是即使是单一应用,仍然要自己管理多个controller之间的优先权和覆盖逻辑,焦点系统不但从技术上,也从交互设计的角度规范化了UI的输入响应,而最妙的是,焦点系统是对视觉障碍人士友好的,现在颇多盲人用读屏软件都是强依赖焦点系统的。

所以时至今日,MVC,尤其是其中controller的功能已经意义不大,若是在控件系统中,再令所有用户输入流经一个controller则可谓不伦不类、本末倒置。MVVM的提出者,微软架构师John Gossman曾言:“我倾向于认为它(指controller)只是隐藏到后台了,它仍然存在,但是我们不需要像是1979年那样考虑那么多事情了”

MVP

1996年,Taligent公司的CTO,Mike Potel在一篇论文中提出Model-View-Presenter的概念。

在这个时期,主流的view的概念跟经典MVC中的那个“永远不应该知道用户输入”的view有了很大的差别,它通常指本文中所述的控件,此时在Mike眼中,输入已经是由view获得的了:

Model-View-Presenter是在MVC的基础上,进一步规定了Controller中的一些概念而成的:

对,所以,不论你按照Mike还是Trygve的理解方式,MVP和MVC的依赖关系图应该是一!模!一!样!的!因为Mike的论文里说了“we refer to this kind(指应用程序全局且使用interactor, command以及selection概念的) of controller as a presenter”。presenter它就是一种controller啊!

把依赖关系画成这样也是醉了啊!不管你信不信我反正是不信啊!

标记语言和MVVM

随着20世纪初web的崛起,HTML跟JS这样标记语言+程序语言的组合模式开始变得令人注目。逐渐推出的Flex、Sliverlight、QT、WPF、JSF、Cocoa等UI系统不约而同地选择了标记语言来描述界面。

在这样的架构中,view(或者说叫控件,不但是从依赖关系上跟程序的其他部件解耦,而且从语言上跟其它部分隔离开来。

标记语言的好处是,它可以由非专业的程序员产生,通过工具或者经过简单培训,一些设计师可以直接产生用标记语言描述的UI。想要突破这个限制使得view跟其它部分异常耦合可能性也更低。

然而这样的系统架构中,MVC和MVP模式已经不能很好地适用了。微软架构师John Gossman在WPF的XAML模式推出的同时,提出了MVVM的概念。

WPF得MVVM正式说明了它的view的概念跟MVC中的view的概念的区别。这里简单画了一下:

在MVVM模式中,数据绑定是最重要的概念,在MVC和MVP中的view和model的互相通讯,被以双向绑定的方式替代,这进一步把逻辑代码变成了声明模式。

结语

从经典MVC到MVVM,UI架构经过数次重大变迁,一些概念也在不断变化,架构和底层环境互相影响、适配,我认为时至今日,经典MVC已经不再是UI架构的正常选项。

更糟糕的是,今天无数经过演绎的MVC实现(如backbone)和科普文,要么是原本作者概念已经很混乱,掺杂私货,要么为了适配现代的标记语言和控件模式,自己修改了经典MVC中的一些概念和耦合关系。实际上今天MVC已经没法作为一种交流的标准词汇了。

写此文,希望大家能了解些历史上的发展历程,莫被不严谨的文章误导。其实本文的相当多观点也是经过演绎的,所以我附上所有原始文献链接,希望大家看了以后能有自己的判断:)也欢迎大家据此指出我理解的错误之处。

转载博文:http://blog.csdn.net/sylcc_/article/details/7346149

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

同步滚动两个DataGrid

拿到这个首先想到的就是重写Scroll方法,可是想想工作量有些大,所以想在Form级别上做做手脚,看看DataGrid的成员列表可以看到这样两个保护性的方法:GridHScrolled Listens for the horizontal scrollbars scroll even…

RISC-V踩坑记----__builtin_clz((x)库函数的应用

RISC-V的确是个好东西,可是,免费的东西往往需要付出代价才能得到了,最近遇到了一个算法中的问题,追了好久,最终追到了这个库函数中,没想到,这个库函数居然还隐藏着一些猫腻。值得记下来啊。 首先…

整蛊偷快递的家伙!不愧是 NASA 工程师

分享个有意思的新闻给大家,一笑之余,也可以学习下文中主角的理工科思维。不知道你有木有过。。快递包裹被别人偷走的经历??包裹历经波折终于到了家门口,结果。。却被人给顺走了!!报警&#xff1…

dns 320 linux,linux 下 dns服务器(三 配置篇)

如何设置一个caching only域名服务器1 设置所谓caching only域名服务器是指一个服务器运行有n a m e d进程,但是并不对任何域(区)的域名信息具有授权,也就是并不向外提供本域的域名匹配信息,不负责I n t e r n e t上对本组织域名解析的应答&…

图解Cisco Packet Tracert之利用TFTP来升级路由器的IOS

对于我们这些学生来说,如果是自学的朋友来说,想摸到真机那实在是太难了,说去买一台呢?买来又没有多大作用,利用dynamips来模拟呢,他本来就是加载的IOS,在flash里面又没有IOS,这时候那…

终于用上gcc-4.1编译的系统了

终于用上gcc-4.1编译的系统了 把PHP、APACHE2、MYSQL又配好了。数据还是原来的数据。posted on 2006-05-19 07:35 浙林龙哥 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/huqingyu/archive/2006/05/19/403972.html

Android中的动画有哪几类?各自的特点和区别是什么?

在 android.view.animation包中有四种基本的动画 ,透明/伸缩/移动/旋转。动画类型Android的animation由四种类型组成XML中alpha渐变透明度动画效果scale渐变尺寸伸缩动画效果translate画面转换位置移动动画效果rotate画面转移旋转…

不指导,一起学习

不敢说指导,只能说以自己的观点来说下这个事情。年前的时候,我一个朋友的朋友也想学电子方面的技术,他毕业后做汽修工作,但是没做多久没离职了,之后在工厂上班一段时间,最近两年帮亲戚一起打理一些生意上的…

linux按键检测结束,关于Linux下按键的检测

写这篇博客是因为自己想做一个fc模拟器,核心代码(6502和ppu的模拟代码)用的原子开发板的代码,人家是从pc向单片机移植,我是反过来了,不过因为写的不错,用函数指针代替了switch方法可以学习一下,so就用了它的…

(翻译)Tricks of the windows game programming Gurus(Windows游戏大师之路) --- 前言(作者:ANDRE LAMOTHE 1999)...

前言:在一篇零编程学习游戏编程的文章文章中提及此书,而且书评很不错,在当时反响很剧烈。因此下了个PDF版的慢慢学习。虽然接触游戏编程很久,玩的五花八门的游戏也有很多,但真正完成的游戏只有一个扫雷游戏。文章中建议…

C语言那年踩过的坑--局部变量,静态变量,全局变量在内存中存放的位置

先看几个概念: 1、bss是英文block started by symbol的简称,通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0。bss段属于静态内存分配。它的初始值也是由用户自己定义的连接定位文件所确定,用户应…

如何阅读3,500万个博客?

博客至今已经出现5年了,目前这股热潮正在愈演愈烈。博客又叫网络日志,现在已经非常普及;跟踪3,500多万个博客的Technorati Inc.称,博客的总数量每6个月就增加一倍。这就带来了一个问题:如何从浩如烟海的信息中找到想要…

u-boot与bootloader及其区别

Bootloader比Bootloader从字面上来看就是启动加载的意思。用过电脑的都知道,windows开机时会首先加载bios,然后是系统内核,最后启动完毕。那么bootloader就相当于手机的bios,它在手机启动的时候根据基带初始化硬件,然后…

assets目录与res/raw目录下文件的区别

assets目录与res/raw目录下文件的区别 assets目录下的文件不会被编译成二进制,直接被打包到apk中。 assets目录中的文件不会在R.Java中建立索引。 assets目录下的文件需借助AssetManager访问。 assets目录下可以建立自己的子目录。 res/raw目录下的文件会被编译成二…

linux gdb 忽略信号,linux gdb调试基本命令

近年来,随着嵌入式技术飞速发展,嵌入式产品随处可见,Linux的应用也越来越广泛。接下来是小编为大家收集的linux gdb调试基本命令,希望能帮到大家。linux gdb调试基本命令1.启动调试前置条件:编译生成执行码时带上 -g,如果使用Makefile&#x…

Adobe Dreamweaver 添加库、标签和属性

您可以在 Dreamweaver 中使用标签库编辑器添加标签库,并将标签和属性添加到标签库中。 添加一个标签库在标签库编辑器(“编辑”>“标签库”)中,单击加号 () 按钮,然后选择“新建标签库”。在“库名称”框中&#xf…

白话debounce和throttle

遇到的问题 在开发过程中会遇到频率很高的事件或者连续的事件,如果不进行性能的优化,就可能会出现页面卡顿的现象,比如: 鼠标事件:mousemove(拖曳)/mouseover(划过)/mouseWheel(滚屏)键盘事件:keypress(基于…

Windows平台下使用Active Directory对Subversion进行权限控制(非完美解决方案)

Windows平台下使用Active Directory对Subversion进行权限控制(非完美解决方案) Windows平台下使用Active Directory对Subversion进行权限控制(非完美解决方案) 目前网上找到的Subversion的配置说明中,关于用户权限控制…

wireshark抓包工具的使用及分析

前段时间看到群里在讨论Wireshark抓包工具,想写一篇使用笔记但一直没来得及写,本篇就通过实例来分享wireshark抓包工具的使用。Wireshark简介 Wireshark 是一个网络封包分析软件。网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详…

EventLoop笔记

node环境 Event Loop各阶段: - timers 阶段:这个阶段执行 setTimeout 和 setInterval 的回调函数。- I/O callbacks 阶段:不在 timers 阶段、close callbacks 阶段和 check 阶段这三个阶段执行的回调,都由此阶段负责&#xff0c…