iOS 面试-设计模式
什么是设计模式?聊聊你所知道的设计模式。
1.代理模式
当一个类的某些功能需要由别的类来实现,但是又不确定具体会是哪个类实现。
代理 + 协议的组合。实现 1 对 1 的反相传值操作。
2.观察者模式
Notification 通知中心,注册通知中心,任何位置可以发送消息,注册观察者的对象可以接收。
KVO 是典型的通知模式,观察某个属性的状态,状态发生变化时通知观察者。
3.MVC 模式
通过数据模型,控制器逻辑,视图展示将应用程序进行逻辑划分。
Model View Control, 把模型 视图 控制器 层进行解耦合编写。
4.单例模式
确保程序运行期某个类,只有一份实例,用于进行资源共享控制
系统实例:[UIApplication sharedApplication]。
5.工厂模式:简单工厂,抽象工厂
通过一个类方法,批量的根据已有模板生产对象。
6.责任链模式
7.桥接模式
8.适配器模式:对象适配器,类适配器
在实际开发中, 代理、观察者和单例大多数情况都是为了数据传递.
而 MVC 可以使代码逻辑更加清晰, 更容易维护.
工厂模式则可以让常用方法重用, 使项目更容易维护.
编程中的六大设计原则
1.单一职责原则:
通俗地讲就是一个类只做一件事,如:
CALayer:动画和视图的显示。
UIView:只负责事件传递、事件响应。
2.开闭原则:对修改关闭,对扩展开放。
要考虑到后续的扩展性,而不是在原有的基础上来回修改。
3.接口隔离原则:使用多个专门的协议、而不是一个庞大臃肿的协议
如:UITableviewDelegate
UITableViewDataSource
4.依赖倒置原则
抽象不应该依赖于具体实现、具体实现可以依赖于抽象。
调用接口感觉不到内部是如何操作的
5.里氏替换原则
父类可以被子类无缝替换,且原有的功能不受任何影响
如:KVC
6.迪米特法则
一个对象应当对其他对象尽可能少的了解,实现高聚合、低耦合
如何设计一个图片缓存框架
参考 SDWebImage 来实现
1. 整体构成:
Manager
内存缓存
磁盘缓存
网络下载
CodeManager:图片解码,图片解压缩
图片的存储是以图片的单向 hash 值为 Key
2. 内存设计需要考虑的问题
存储的 Size 因为内存的空间有限,我们针对不同尺寸的图片,给出不同的方案
10K 以下的 50 个
100Kb 以下的 20 个,100kb 以上的 10 个
3. 淘汰的策略
内存的淘汰策略采取 LRU(最近最少使用算法)
4. 触发淘汰策略的时机有三种
(1).定期检查(不建议,耗性能)
(2).提高检查触发频率(一定要注意开销): 可以选择前后台切换的时候;每次读写的时候
5. 磁盘设计需要考虑的问题
存储方式
大小限制(有固定的大小)
移除策略(可以设置为7天或者15天)
6. 网络设计需要考虑的问题
(1)图片请求的最大并发量
(2)请求超时策略
(3)请求优先级
7. 图片解码
应用策略模式,针对 jpg、png、gif 等不同的图片格式进行解码
8. 图片解码的时机: 避免在主线程解压缩、解码,避免卡顿
(1)在子线程图片刚下载完时
(2)在子线程刚从磁盘读取完时
如何设计一个时长统计框架
1.记录器
页面式记录器; 流式记录器; 自定义式
2.记录管理者
内存记录缓存; 磁盘存储; 上传器
3.如何降低数据的丢失率?
定期写入磁盘
每当达到某个值的时候,就写入磁盘
4.记录上传的时机
前后台切换的时候可以上传
从无网到有网切换的时候可以上传
5.上传时机的选择
立即上传; 定时上传; 延时上传
常见的跨模块通信方式
1. 路由 URL 统跳方案
优点:URL 本身是一种跨多端的通用协议。使用路由URL统跳方案的优势是动态性及多端统一 (H5, iOS,Android,Weex/RN)
缺点:能处理的交互场景偏简单
所以一般更适用于简单 UI 页面跳转。一些复杂操作和数据传输,虽然也可以通过此方式实现,但都不是很效率。
目前天猫和蘑菇街都有使用路由 URL 作为自己的页面统跳方案,达到解耦的目的。
2. 基于反射的远程调用封装
优点:调用简单方便,代码自动补全和编译时检查都仍然有效
缺点:category 存在重名覆盖的风险,需要通过开发规范以及一些检查机制来规避。
同时 Mediator 只是收敛了 hardcode, 并未消除 hardcode, 仍然对开发效率有一定影响。
业界的 CTMediator 开源库,以及美团都是采用类似方案。
3. 基于面向协议思想的服务注册方案
优点:调用简单方便。代码自动补全和编译时检查都有效。
实现起来也简单,协议的所有实现仍然在模块内部,所以不需要写反射代码了。
同时对外暴露的只有协议,符合团队协作的“面向协议编程”的思想。
缺点:如果服务提供方和使用方依赖的是公共模块中的同一份协议(protocol), 当协议内容改变时,会存在所有服务依赖模块编译失败的风险。
同时需要一个注册过程,将 Protocol 协议与具体实现绑定起来。
蘑菇街的 ServiceManager 和阿里的 BeeHive 都是采用的这个方案。
4. 通知广播方案
基于通知的模块间通讯方案,实现思路非常简单, 直接基于系统的 NSNotificationCenter 即可。
优点:实现简单,非常适合处理一对多的通讯场景。
缺点:仅适用于简单通讯场景。复杂数据传输,同步调用等方式都不太方便。
模块化通讯方案中,更多的是把通知方案作为以上几种方案的补充。
参考:有赞移动 iOS 组件化(模块化)架构设计实践