MVC 设计模式

如何对 ViewController 瘦身?

objc.io 是一个非常有名的 iOS 开发博客,它上面的第一课 《Lighter View Controllers》 上就讲了很多这样的技巧,我们先总结一下它里面的观点:

  • 将 UITableView 的 Data Source 分离到另外一个类中。

  • 将数据获取和转换的逻辑分别到另外一个类中。

  • 将拼装控件的逻辑,分离到另外一个类中。

你想明白了吗?其实 MVC 虽然只有三层,但是它并没有限制你只能有三层。所以,我们可以将 Controller 里面过于臃肿的逻辑抽取出来,形成新的可复用模块或架构层次。

我个人对于逻辑的抽取,有以下总结。

将网络请求抽象到单独的类中

新手写代码,直接就在 Controller 里面用 AFNetworking 发一个请求,请求的完数据直接就传递给 View。入门一些的同学,知道把这些请求代码移到另外一个静态类里面。但是我觉得还不够,所以我建议将每一个网络请求直接封装成类。

把每一个网络请求封装成对象其实是使用了设计模式中的 Command 模式,它有以下好处:

  • 将网络请求与具体的第三方库依赖隔离,方便以后更换底层的网络库。实际上我们公司的 iOS 客户端最初是基于 ASIHttpRequest 的,我们只花了两天,就很轻松地切换到了 AFNetworking。

  • 方便在基类中处理公共逻辑,例如猿题库的数据版本号信息就统一在基类中处理。

  • 方便在基类中处理缓存逻辑,以及其它一些公共逻辑。

  • 方便做对象的持久化。

大家如果感兴趣,可以看我们公司开源的 iOS 网络库:YTKNetwork。它在这种思考的指导下,不但将 Controller 中的代码瘦身,而且进一步演化和加强,现在它还支持诸如复杂网络请求管理,断点续传,插件机制,JSON 合法性检查等功能。

这部分代码从 Controller 中剥离出来后,不但简化了 Controller 中的逻辑,也达到了网络层的代码复用的效果。

将界面的拼装抽象到专门的类中

新手写代码,喜欢在 Controller 中把一个个 UILabel ,UIButton,UITextField 往 self.view 上用 addSubView 方法放。我建议大家可以用两种办法把这些代码从 Controller 中剥离。

方法一:构造专门的 UIView 的子类,来负责这些控件的拼装。这是最彻底和优雅的方式,不过稍微麻烦一些的是,你需要把这些控件的事件回调先接管,再都一一暴露回 Controller。

方法二:用一个静态的 Util 类,帮助你做 UIView 的拼装工作。这种方式稍微做得不太彻底,但是比较简单。

对于一些能复用的 UI 控件,我建议用方法一。如果项目工程比较复杂,我也建议用方法一。如果项目太紧,另外相关项目的代码量也不多,可以尝试方法二。

构造 ViewModel

谁说 MVC 就不能用 ViewModel 的?MVVM 的优点我们一样可以借鉴。具体做法就是将 ViewController 给 View 传递数据这个过程,抽象成构造 ViewModel 的过程。

这样抽象之后,View 只接受 ViewModel,而 Controller 只需要传递 ViewModel 这么一行代码。而另外构造 ViewModel 的过程,我们就可以移动到另外的类中了。

在具体实践中,我建议大家专门创建构造 ViewModel 工厂类,参见 工厂模式。另外,也可以专门将数据存取都抽将到一个 Service 层,由这层来提供 ViewModel 的获取。

专门构造存储类

刚刚说到 ViewModel 的构造可以抽奖到一个 Service 层。与此相应的,数据的存储也应该由专门的对象来做。在小猿搜题项目中,我们由一个叫 UserAgent 的类,专门来处理本地数据的存取。

数据存取放在专门的类中,就可以针对存取做额外的事情了。比如:

  • 对一些热点数据增加缓存

  • 处理数据迁移相关的逻辑

如果要做得更细,可以把存储引擎再抽象出一层。这样你就可以方便地切换存储的底层,例如从 sqlite 切换到 key-value 的存储引擎等。

小结

通过代码的抽取,我们可以将原本的 MVC 设计模式中的 ViewController 进一步拆分,构造出 网络请求层、ViewModel 层、Service 层、Storage 层等其它类,来配合 Controller 工作,从而使 Controller 更加简单,我们的 App 更容易维护。

另外,不知道大家注意到没,其实 Controller 层是非常难于测试的,如果我们能够将 Controller 瘦身,就可以更方便地写 Unit Test 来测试各种与界面的无关的逻辑。移动端自动化测试框架都不太成熟,但是将 Controller 的代码抽取出来,是有助于我们做测试工作的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值