关于“幽灵架构”的总结:适用场景与方法重载
来源:互联网 发布:淘宝中老年夏季女装 编辑:程序博客网 时间:2024/04/28 21:36
前几篇博文对“幽灵架构”做了用法的介绍和相关技术点的补充,本文是一篇总结性质的文章,分析该架构的适用场景和限制,首先让我们回顾一下iOS开发的MVC模式,参考斯坦福公开课里Paul老爷子的讲解,如下图所示:
在MVC模式下Model和View是不能直接通信的,在“幽灵架构”体系中Model和View依旧不能直接通信,在传统的MVC中,这种通信的阻隔很多时候是因为在没有得到Model和View实体的情况下无法完成二者的数据绑定,在过去你可能想过在View中写一个方法来接受一个模型,然后写具体的实现,在没有泛型的帮助下只能用方法的重载来做,没有协议扩展的情况下需要在父类和写重复的代码中做选择。
在“幽灵架构”体系中,通过ModelType和ViewType可以在不借助控制器的帮助下实现二者的逻辑绑定,依旧是使用了方法传值的用法,Controller起到了“开关”的作用,依靠泛型和协议对数据类型进行了约束,并且避免了重复代码,不需要在意数据源的同构和异构。
我们需要在Controller中创建Model和View的实例,并且和MVC一样可以对Model和View做处理,但是Model和View之间的逻辑关系是定义在View的getData中的,比如Demo中Event的Cell会被标注为红色,如果要通过修改Controller的标志位来影响Model和View之间的逻辑,比如Demo中在Controller中加入一个开关,点击后会互换Event和Festival的背景色,这就属于Controller中引入了标志位来影响View和Model的逻辑,此时如果要继续维持“幽灵架构”的体系,那么需要重载giveData和getData方法,传入Controller中的标志位。首先给getData增加默认实现,因为在View的代码中我们只想重写需要的重载的方法:
//视图使用的协议protocol ViewType{ func getData<M:ModelType>(model:M)}//数据使用的协议protocol ModelType{}//定义默认方法giveDataextension ModelType{ func giveData<V:ViewType>(view:V){ view.getData(self) }}extension ViewType{ func getData<M:ModelType>(model:M){ }}
为了维持“幽灵架构”的灵活性,我们重写了giveData和getData,不是在具体的遵守者中重写,而是直接扩展协议:
extension ModelType where Self:HasDate{ func giveData<V:ViewType>(view:V,tag:Bool){ if let tableCell = view as? ShowedTableViewCell{ tableCell.getData(self,tag:tag) } }}extension ViewType where Self:ShowedTableViewCell{ func getData<M : ModelType>(model: M,tag:Bool){ }}
现在不需要修改所有的Model,但是需要在View中重写新定义的方法:
func getData<M : ModelType>(model: M,tag:Bool) { //这里不能写成guard let dateModel = model as? DateViewModel else{}令我有些意外 guard let dateModel = model as? HasDate else{ return } //处理相同属性 dateLabel.text = dateModel.date //处理数据源异构 if let event = dateModel as? Event{ MixLabel.text = event.eventTitle backgroundColor = tag ? UIColor.redColor():UIColor.whiteColor() } else if let festival = dateModel as? Festival{ MixLabel.text = festival.festivalName backgroundColor = !tag ? UIColor.redColor():UIColor.whiteColor() } }
这是协议扩展的另一个神奇之处:不会引入多余的状态,避免了“上帝类”的出现,如果你的工程中有其他的Model和View的绑定,不会受到任何影响。最后一步,修改Controller中的数据绑定:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(cellReusedID, forIndexPath: indexPath) as! ShowedTableViewCell //调用重载的方法 dataList[indexPath.row].giveData(cell,tag:true) return cell }
现在尝试向tag传入true和false看看效果吧:
tag传入false
tag的值取决于Controller,从上面的例子中看出在Controller中切换View和Model的绑定逻辑是完全没问题的。之前讲过giveData方法是为了在异构数据源中避免Box类型的出现,提高运行效率,针对同构的数据源,我们只需要重载getData并在控制器中直接使用getData对数据进行捆绑就好了。
所以,我之所以在最初的文章中称“幽灵架构”为MV,其实并没有弱化控制器的职责,但是把控制器中有关于模型和视图逻辑绑定的代码移到了View中,并且集中在了getData一个方法中,便于维护,为控制器减压,所以其实这是一个“伪架构”。从上面的示例中可以看到,MVC和MVVM能做到的“幽灵架构”一样能做到,并且比MVC中控制器的代码更好维护,比MVVM少写了很多代码。“幽灵架构”今后的发展,需要经历时间的考验了。
- 关于“幽灵架构”的总结:适用场景与方法重载
- 关于“幽灵架构”的补充说明4:协议的应用场景与局限性
- 垂直水平居中的方法总结和适用场景
- Android MVC与MVP架构适用场景
- 关于“幽灵架构”的补充说明1:协议中的方法定义
- Java的幽灵引用定义与使用场景
- 关于“幽灵架构”的补充说明5:改造控制器
- Redis的基本数据类型与适用场景
- memcache适用和不适用场景总结
- MongoDB适用和不适用场景总结
- 关于方法的覆盖与重载
- Nodejs的适用场景
- Hive的适用场景
- alluxio的适用场景
- volatile的适用场景
- volatile的适用场景
- 关于方法重写和方法重载的总结
- 三种常用的素数判断方法以及适用场景
- linux初接触
- Swift设计模式之保护代理模式
- 正则表达式 捕获组,向前引用,零宽度断言,贪婪量词,惰性量词以及支配量词
- pykafka的消息队列的使用
- Swift设计模式整理
- 关于“幽灵架构”的总结:适用场景与方法重载
- git 远程操作详解
- 真机测试证书问题
- 微博的MySQL数据库优化实践经验
- Android播放系统声音源码
- Java并发编程之2——同步工具类的使用(CountDownLatch,CyclicBarrier,BlockungQueue,Semaphore)
- Android单点触控技术,对图片进行平移,缩放,旋转操作
- MAC下如何把android源码导入到eclipse中阅读查看
- 前端工程师的发展之路