专栏首页我杨某人的青春满是悔恨常见的客户端架构解析

常见的客户端架构解析

一千个程序员眼中有一千种 MVC

SmallTalk MVC

MVC.gif

Models

  • Models 表示知识。
  • 一个 Model 可以是单个对象,也可以是一些对象的组合结构。
  • Model 和它的部件之间可能有一对一的通信。
  • 对 Model 的所有者(View)来说,它如实地反映了真实世界。
  • Model 是问题的一个可标示部分。
  • 某个 Model 的所有节点都应该处在同样的问题等级,将面向问题的节点(如日历中的预约)和实现细节(如图形)混在一起是不好的。

Views:

  • View 是它的 Model 的(可见)表示。
  • 它会重点关注 Model 中的某些属性而忽视其它的,因此它也是一个展示过滤器。
  • View 和它的 Model(或者 Model 的一部分)连接。它以问问题的方式得到展示所需的数据,发送合适的消息来更新 Model。所有这些问题和消息都在 Model 的术语中,因此 View 必须知道它所展示的 Model 的属性的语义。

Controllers

  • Controller 是用户和系统的桥梁。
  • 它指定相关的 Views 让它们将自己展示在屏幕的适当位置。
  • 它通过菜单或者其它可以支持命令和数据的形式来表示用户的意图。
  • Controller 不应该去补充 Views,比如它不会在几个 View 之间绘制箭头把它们连接起来。
  • View 永远不会知道用户的输入,譬如鼠标操作和键盘点击。在 Controller 可以写一个方法向 View 发送消息,它可以精确模拟用户的一系列指令。

Editors

  • 一个 Controller 和它所有的 Views 相关联,它们被称为 Controller 的部件。
  • 某些 Views 提供一种特殊的 Controller——Editor。
  • Editor 允许用户修改 View 所展示的信息。
  • 这样的 Editor 可能被插入 Controller 和 View 之间,它表现得像 Controller 的一个扩展。
  • 一旦编辑操作结束,Editor 被移除。
  • Editor 通过它所连接的 View 的 metaphors(隐喻,象征)来和用户交流,因此 Editor 和 View 是强关联的。
  • Controller 只能向 View 请求从而得到一个 Editor 的引用,别无他法。

观点

以上是对 MVC 原始论文的整理翻译。

在 MVC 中,V 可以和 C 通信,V 可以和 M 通信。

最早的 MVC 于 1979 年提出,当时还需要程序员全权处理用户输入——Controller 的职责。而现在,大部分事情已经被操作系统做了,我们已经做不到“View 永远不会知道用户的输入”,我们也不太需要 Editor,因为这些已经被封装进UITextField之类的控件中,View 本身就具备一定的交互功能。用户操作往往被封装成“事件”传递给 View。

所以真正的 MVC 是一种过时的架构。

Apple MVC

Apple MVC.png

Model Objects

  • Model Objects 包括应用所需的数据,并且定义数据处理的逻辑。
  • Model 和 View 之间不该有明确的关联。
  • 用户在 View 层的操作会通过 Controller 增加或改变 Model。
  • Model 一旦改变(譬如从网络获取了新数据),它会通知 Controller,Controller 再去更新 View。

View Objects

  • View Object 是应用中用户可以看到的部分。
  • View 知道如何绘制自己,可以响应用户操作
  • View 展示 Model 中的数据,并且允许编辑这些数据。尽管如此,View 和 Model 是完全解耦的
  • View 通过 Controller 得知 Model 中数据的变化;并且将用户发起的变化通过 Controller 反映到 Model。

Controller Objects

  • Controller 是 View 和 Model 之间的中间人。
  • Controller 也可以用来设置和协调应用的任务、管理其它对象的生命周期。
  • Controller 会将 View 层的变化反映到 Model 层,也会将 Model 层的变化反映到 View 层显示出来。

观点

Apple 所谓的 MVC 跟原始的 MVC 基本已经毫无关系……在这里 C 成了一个中介者,用以协调 V 和 M。

这个模式其实没有特别大的问题,但是由于 Cocoa 中的 ViewController 还承担了 View Container 的工作,我们在日常开发中又容易把 Model 层设计得过于单薄(比如只是一个单纯的数据对象),从而导致 Controller 中有大量本该放在 View 和 Model 中的代码。

所以这是一个最容易被滥用的模式。

MVVM

MVVM.png

ViewModel

  • 一个抽象的视图(AbstractView)。
  • 包含概念:视图状态(ViewState)、数据转换器(ValueConversion)、操作 Model/ViewModel 的指令。

数据绑定

  • 需要一种绑定机制将 View 和 ViewModel 连接起来(View 和 ViewModel 可以用不同语言编写)。

观点

MVVM 由微软架构师 John Gossman 于 1996 年提出,在提出这个概念以前,他们团队早已在实践这个架构了。由于 MVVM 是 MVC 的一种改进,M 和 V 部分和 MVC 是类似的。而 Gossman 认为在现代 GUI 系统中,C 的大部分工作已经由系统帮你做了,所以 C 并没有被抛弃,而是隐藏到幕后了。

MVVM 中的 VM 承担了状态管理、数据转换、操作处理之类的任务,它早先被用于 WPF(View 层由 XMAL 编写,且内建了绑定机制),但写 WPF 并不一定要用 MVVM,你完全可以将 View 和 Model 直接绑定——如果你的程序足够简单。

由于在 iOS 中并没有一个内建的绑定机制,很多人觉得在项目中多一层数据转换层就是 MVVM 了,这有一些片面。我还是觉得真的要用 MVVM 就必须建立一套绑定机制,可以利用 RxSwift 和 RAC 之类的第三方库,或者自己撸一套。

MVP

Passive View variant of MVP.png

1996年,Mike Potel 在一篇论文中提出 Model-View-Presenter 的概念。这个时候的 View 已经跟 MVC 刚诞生时的 View 全然不同了,它可以接受用户输入。MVP 的主要思想是用户输入由 V 流进,V 通过 P 更新 M,同时 V 跟 M 之间还是跟 MVC 中一样,V 可以调用 M 的接口,M 通过观察者模式向 V 广播自身的更新。

同 MVC 一样,而今的 MVP 与最早的 MVP 也相距甚远。现在为人所普遍接受的 MVP 是,V 和 M 完全解耦,通过 P 进行通讯。但和 Apple MVC 不同的是,P 并不包含生命周期控制之类的职责,而且一般是由 V 去持有 P。

观点

MVP 似乎在 Android 开发中比较流行,我没有实践过,不敢妄言。

VIPER

VIPER.png

由 View、Interactor、Presenter、Entity、Router 组成。

观点

同样没有实践过……但直观上感觉是把 MVP 进行了进一步拆分——Presenter 拆为 Presenter 和 Router,Model 拆为 Interactor 和 Entity。

小结

对于结构划分,还是要根据项目规模来,规模大就分层细一点,规模小就粗一点。因为分层越多,层与层之间的通信成本就越高。通信方面可以采取各种手段——接口调用、观察监听、数据绑定等。

我个人比较倾向于分为 View、Model、ViewModel、Router 这几层,以数据绑定为基础进行通信。

各个层最好都定义一个协议来确认各自的职责,可以有一些默认实现。

参考资料:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 走进 RxSwift 之冷暖自知

    前段时间身体跟心态都出了点问题,博客也很久没更新了。细心的朋友可能发现我的个人介绍换了,由原先高冷装逼的“谢绝转载”变为略显矫情的“人生谁能不迷茫”了。不知道大...

    Sheepy
  • 仿【每天】首页动画

    最近工作一直挺忙,偶有闲暇时都在翻看《iOS Animations by Tutorials》,受益良多,尤其是让我对Core Animation有了更深入的理...

    Sheepy
  • iOS 开发中的 ViewModel

    MVVM 这个模式可能大家耳朵都听出茧了,但却没有多少人真正在项目中应用过,毕竟 Cocoa Touch 整体是基于“MVC”的,没有 Controller 根...

    Sheepy
  • 【答疑解惑】android activity的作用

    群友问了一个关于android apk开发中activity的问题,如下: ? 我们下面要说一下activity的作用: 首先,Activity是Android...

    程序员互动联盟
  • Android实现时钟特效

    本文实例为大家分享了Android实现时钟特效的具体代码,供大家参考,具体内容如下

    砸漏
  • LeetCode 实战:「图解」二叉树中的最大路径和

    本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径 至少包含一个节点 ,且不一定经过根节点。

    五分钟学算法
  • command line subversion for windows

    安装 Slik SVN 之后,进入dos, 输入svn help,所有的命令和相关的信息都出来了

    meteoric
  • 微信终于坐不住了,要帮你管一管朋友圈里的「微商」

    知晓君
  • Computer HDU - 2196

    A school bought the first computer some time ago(so this computer's id is 1). Du...

    ACM算法日常
  • tcp回显客户端发送的数据

    skylark

扫码关注云+社区

领取腾讯云代金券