在我们日常的开发中设计模式伴随着项目的各个模块,巧妙地使用设计模式可以让我们写出更高效,简洁,优美的代码。可是因为对于设计模式的不熟悉,很多高效的设计模式并没有被很好地使用起来,而最近也正好在review同事和自己曾经写的一些代码,然后在优化的过程中谈一下我们在项目中使用设计模式做出的一些优化。当然只是个人看法,有任何的不足欢迎拍砖,大家一起探讨和成长。

1.在项目中使用delegate pattern(代理模式)和block的抉择

之前在技术交流群中看到技术大神在争论block和delegate使用哪一种该如何抉择的问题,看到有人说delegate传递的是指针而block传递的是一个结构体,在这个角度出发确实是delegate更好一些,但是在我们实际的开发环境中,我更愿意结合具体的业务场景做出不一样的选择,因为delegate在代码的可读性上是不如block好的,具体而言我们主要做了如下的抉择。

首先在网络请求层的处理上对delegate和block都做了封装,原因就是在具体的业务中会出现在A类中发送了请求,可是我们返回的数据创建的对应模型要在B类中才会去调用,这个时候我们使用block来传递数据模型,因为这时使用代理可能要封装两层甚至多层的代理这里无疑就将代码的可读性变得很差。如果模型传递的更多层,代码会显得异常混乱。

第二在实际开发中有些复杂界面会用到dispatch_group_t的情况,这个时候如果是要对网络请求做合并处理的,如果这个时候在同一个方法中我们发送了两个甚至更多的网络请求,此时如果要是使用delegate来回调返回结果,一般会将dispatch_group_t声明成一个属性,在代理中使用dispatch_group_leave(self.group)这样的方式来获取回调结果,然后在dispatch_group_notify中做统一的处理,我认为这样对于group的内存管理就变得不在合理,所以这个时候我是用的block。 剩下的在一个界面中的时候,我更多的会用#prama mark 的方法区分出一个请求,用代理的方式会写请求。

当然除了网络请求层的处理之外,我们是不是在其他地方也对delegate和block有过抉择呢,这一点上一定会有的。我记得前不久我们在做 <U运动>健身教练直播版本开发的过程中就遇到过,我相信大家对于直播界面是不陌生的,如果点击主播头像,观众头像,评论区的昵称都会显示用户的资料弹窗的。可是这三个部分被拆分到了三个小的试图类中,当时同事提出每个点击事件用block的方式进行回调,写一个manager管理类,对弹出用户资料进行统一的处理,我想很多人第一时间都会想到这样的处理方案,但是后来却用了代理的方案。

方案的代码结构如上图,就是一个简单的demo,也就是说我们将代理模式进行了区分,所有获取用户资料的点击事件都走baseMethod1的代理 一样可以做到所有用户的获取资料的点击事件走到controller的一个方法中,也不再需要去为此创建一个manager,甚至也不需要在每个试图中区公开一个回调的方法,感觉在代码的简洁和清晰上都有了提高,此外也可以兼容每个试图有自己的回调事件。所以在delegate模式和block的抉择中并不是一定的,要结合具体的业务的场景做出自己的分析然后做出选择。

2.关于adapter pattern(适配器模式)的使用

我想一些同学在陪伴项目成长的过程中很多都遇到过这样的一个问题,就是将服务器返回的数据转换成一个数据模型然后传入各个试图的接口渲染界面,但是有的时候产品告诉我们,我的用户资料想多要一个参数来呈现,如果接口名命名成多个参数名的形式,那么势必会很麻烦改动很多曾经调用的地方。这个时候有的小伙伴会说接口传入参数是一个类就好了,但是如果用户资料要在多个界面进行呈现的方式是一样的,但是每个界面整体返回的数据又是不一样的情况下,如果接口用类来做参数,可能就需要在拆分出来的用户资料的试图中提供很多的接口,然后暴露给界面调用,显然这样的方式也是不合理的。所以这个时候怎么样解决呢,于是出现了适配器模式。代码结构如下

适配器模式使用

如果在适配器模式下,我们再给多处需要用到的试图传入参数的时候就不用接口定义多个参数或者是类了,这个时候我们定义的参数是遵守某个协议的数据模型,我们在每个界面返回的数据模型中遵守对应的协议就可以了。如果产品再来告诉我们改需求,我们就在协议中对应的添加方法,然后搜索下遵守对应协议的类实现这个方法就好了,界面的处理就会变得简单。当然对于适配器的使用我只是简单的分析。它绝不只是用在适配界面,我们在真实的项目中进入有些controller也是用的这样的方案,甚至适配器协议还要再去做遵守协议的操作,在它的上层在创建一个适配器,这个就需要结合具体的业务场景了。但是适配器在增加代码的可读性以及简化代码上真的可以给我们很大的帮助,更好的使用还是需要小伙伴们不断地尝试和想象的~~~

3.关于singleton pattern(单例模式)的使用

我想对于绝大多数开发者而言,这种开发模式对于我们而言都是再熟悉不过的。这里要说单例模式的原因是我认为单例在很多的项目中可能有些被过分的使用了,一个项目中可能会出现几十个甚至更多的单例。

我们都知道,在一个单例被创建之后会伴随客户端的整个生命周期,在程序结束之前单例是不会被释放的,所以从内存管理的角度上单例的使用是应该被注意的。应该知道什么场景下我们适合使用单例,在什么样的业务场景下我们可以避免使用单例以节省我们的内存空间。比如说加入我们做了一个直播,有些同学可能为了记录用户是不是在直播中去创建一个单例来判断用户当前的状态,然后限制用户的一些行为。其实这样的场景下,我认为使用单例就是一种不合理的行为,因为在这种模式下,我们完全可以在直播管理类中创建一个类方法创建一个方法,将当前状态存储在NSUserDefault中进行状态的判断,这样节省了对应的内存,也避免了不合理的浪费内存空间,淡然和这里相似的距离有很多。希望处理不当的同学可以检查一下自己的项目,做一个更优的处理方案。

4.一些其他的设计模式中可能需要注意的问题

除了上边的最常用的设计模式之外,我们在项目中常用的设计模式还有工厂模式,观察者,策略等模式和部分项目中用到的中介者,模板,享元等模式。

首先想说的就是观察者模式,在iOS实际开发中,我想大家都用到过NSNotificationCenter和KVO或者FBKVO.但是我想不是所有同学都知道NSNotificationCenter 的observer 收到消息的方法中所在的确切线程的。其实收到消息后执行的方法所在的线程是和post消息时所在线程是一致的,所以这是可能就会出现线程安全的问题,虽然苹果在官方的文档中说做过处理,但是在实际开发中并不意味着不会出现问题。具体可以参考这篇文章,里边介绍了出现问题的场景,在我们的项目中使用KVO时遇到过这样的情况的。

至于策略模式,我想大家日常的开发中都有用到过,只是我们有些同学不知道这个叫策略而已~~~其实策略的使用使用真的可以大幅度的提升程序的可读性的,所以不知道的小伙伴一定要百度一下,我在这里就不详细介绍啦。

而中介者模式个人感觉主要用在组件化开发中做URL的跳转使用,我们的项目一直希望想向组件化开发的方向做努力,所以最近可能会深入的研究这一部分,如果有了成果在和童鞋们分享,要说的太多,这里就不做扩展了。

模板模式在项目中的使用其实是可以和适配器模式相结合一起来玩的,所以研究过适配器的小伙伴,对于这里一定再熟悉不过,如果对于这块不是很了解,真的建议很好地去进行学习和关注,良好的代码质量很重要。

最后说道享元模式,我说很少的项目中用到其实是个很严重的错误,因为每个项目我相信一定都会有tableview而它的cell复用池机制就是基于享元模式设计的,严格上说享元模式在企业项目中被自己设计和使用还是比较少的。但是当我们需要复用大量数据的时候考虑到性能等方面的问题,不防考虑下这个模式,然后做相应的优化,一定会有意想不到奇效~~~

文章的最后,想说其实我这个人很懒,不喜欢写文章,自己写的一些小实验也都傻傻的停留在了自己的电脑上,但是最近身边发生的一些事让我的态度有了改变,所以从今以后,我应该会强制的要求自己每周至少写一篇满满都是自己浅显看法的文章,将自己的小想法和无聊生产的小轮子都放到git上去,有任何意见和不满欢迎在这里吐槽,拍砖。当然更希望可以和热爱iOS开发的童鞋们一起成长~~~

浅谈设计模式在iOS开发实战项目中的应用相关推荐

  1. nstruts2.0发布前奏---浅谈struts和依赖注入在项目中的应用

    我喜欢struts,喜欢ibatis,喜欢spring,但我却喜欢.net,这实在是件很矛盾的事情..net很好用,但在做项目的过程,总觉得缺少了点什么,对了,是框架.在java的世界里,有着许多成熟 ...

  2. 设置tableview的滚动范围--iOS开发系列---项目中成长的知识三

    设置tableview的滚动范围 有时候tableview的footerview上的内容需要向上拖动界面一定距离才能够看见, 项目中因为我需要在footerviw上添加一个按钮,而这个按钮又因为这个原 ...

  3. iOS 控制section不悬停 --- iOS开发系列 ---项目中成长的知识八

    一般情况下,tableview中的section是会默认不随着tableview的滚动而滚动的,而是会等到属于这个section的cell滑完过后,然后往上顶(不知道大家能不能听懂=_=!) 有些时候 ...

  4. iOS 导航栏遮挡问题 --- iOS开发系列 ---项目中成长的知识七

    不知大家有没有遇见过自己写的tableview被导航栏遮挡住的问题,反正我是遇见过! 因为在ios7以后所有的UIViewController创建后默认就是full Screen的,因此如果带导航栏的 ...

  5. 最新仿映客直播APP开发实战项目IOS开发实战8天(最全最新)

    最新仿映客直播APP开发实战项目IOS开发实战8天 第 1 章:直播准备 1: [录播] 课程大纲介绍 09:56 2: [录播] 了解直播技术和腾讯云直播 09:54 3: [录播] 基础封装 23 ...

  6. 浅谈 unix, linux, ios, android 区别和联系

    浅谈 unix, linux, ios, android 区别和联系 网上的答案并不是很好,便从网上整理的相对专业的问答. 1.UNIX 和 Linux UNIX 操作系统(尤尼斯), 是一个强大的多 ...

  7. Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序

    Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序 C#原本是用来编写Windows以及Windows Phone的应用程序.自从Xamarin问世后,C#的作用就发生了很大的变化. ...

  8. Xamarin iOS开发实战上册-----2.2.2 使用代码添加视图

    Xamarin iOS开发实战上册-----2.2.2  使用代码添加视图 如果开发者想要使用代码为主视图添加视图,该怎么办呢.以下将为开发者解决这一问题.要使用代码为主视图添加视图需要实现3个步骤. ...

  9. 浅谈iPhone和iPad开发中的图标设置

    浅谈iPhone和iPad开发中的图标设置 图标大小问题 我们的辛辛苦苦做出来的应用程序在iPhone上的表示仅仅是一个图标,对这个图标不可以不谨慎对待,不能因为大小不对头这些小问题而失真啊什么的. ...

最新文章

  1. 260万奖金池!目标检测新赛事来了
  2. sqoop mysql parquet_sqoop一些语法的使用
  3. python读取txt文件并写入excel-Python读excel生成数据存入txt文件
  4. 分布式中Redis实现Session终结篇
  5. (笔试题)小米Git
  6. python3的3D实战 -基于panda3d(3)
  7. 6.29 Vue 第二天 学习笔记
  8. 基于Spark的Als算法+自迭代+Spark2.0新写法
  9. EnforceLearning-在线学习-被动强化学习/评价学习
  10. linux服务器开放防火墙和端口,以及查询状态
  11. 图书管理系统(微信、后台、网页端)总结
  12. 4538: [Hnoi2016]网络
  13. 有关SQL Server 2008你一定要知道的八件事 之三
  14. 浅谈jQuery Mobile设计思想
  15. laravel5.5表单验证
  16. 1010 一元多项式求导 (25 分)—PAT (Basic Level) Practice (中文)
  17. 解决使用redis作为session缓存 报错 Error: no such key 的问题
  18. iframe中加载html页面,jQuery - 动态创建iframe并加载页面
  19. 课堂经验值管理小程序_小程序刷新课堂评价 “量子奖状”能量大
  20. “WebProxyWrapper”的对象强制转换为类型“System.Net.WebProxy

热门文章

  1. 你真的知道flex: 1;是什么意思吗?
  2. 做游戏,不加班行不行?
  3. Python爬取百度图片搜索结果
  4. 计算机机房综合布线预算表,综合布线工程预算表.ppt
  5. 摩登家庭第一季第一集剧本 侵删谢谢
  6. 【稳定性day4】美团外卖高可用的演进之路 - 日活两千万的挑战
  7. 轴承故障诊断分类中常用的一些数据集介绍和获取方法
  8. 石油公路工程都在用的光纤测试仪是什么型号
  9. 逆风撑船,文旅地产的前方是什么?
  10. 新课程改革的理论基础究竟是什么