iOS常用设计模式总结

很多刚入门的iOS开发者经过短期训练,都可以熟练的调用API,这时候,写一个tableView,实现一个小动画,独立完成一个交互的功能,已经不在话下。但同时,iOS开发者也会遇到技术上的第一个瓶颈——即拥有独立开发一个功能的水平,却似乎并未达到独立开发一个App的水平;看似什么都会做,什么都能做,却总是不能在第一时间想到最佳方案;功能是完成了,然而效率并不高,代码逻辑在日后也可能需要返工重构。
我认为,突破这个瓶颈的捷径就是掌握设计模式。设计模式是前人总结的。面对开发中常见问题的解决方案——它们行之有效,便于理解,适合举一反三。简单点儿说,设计模式就是程序开发的套路和模板。熟练掌握设计模式,可以提高开发效率,节省开发时间。这样,我们就可以站在前人的肩膀上,去研究、解决那些具有挑战性和未曾解决过的问题。

一、平常开发中用到的设计模式

iOS开发中的设计模式有很多,一般常见的有以下7种。

  • MVC:它是应用的一种基本架构,主要目的是将不同的代码归并为不同的模块,做到低耦合、代码分配合理、易于扩展维护。
  • 装饰模式(Decorator):它可以在不修改原代码的基础上进行扩展。注意它与继承最大的区别是:继承时,子类可以修改父类的行为,而装饰模式不希望如此。
  • 适配器模式(Adapter):它将一个类的接口转换为另一个类的接口,使得原本互不兼容的类可以通过接口一起工作。
  • 外观模式(Facade):它用一个公共接口来连接多个类或其他数据类型。公共接口让多个互相之间保持独立,解耦性能良好。同时,使用接口时,外部无须理解其背后复杂的逻辑。另外,就算接口背后的逻辑改变也不影响接口的使用。
  • 单例模式(Singleton):此模式保证对于一个特有的类,只有一个公共的实例存在。它一般与懒加载一起出现,只有被需要时才会创建。单例模式的例子有UserDefaults.standard,UIApplication.shared和UIScreen.main。
  • 观察者模式(Observer):它定义对象之间的一种一对多的依赖关系,每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。在iOS中的典型实现是NotificationCenter和KVO.
  • 备忘录模式(Memento):它在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将改对象恢复到保存之前的状态。
    可以把上面7种模式归为一下3类。
  • 创建型(Creational):单例模式(Singleton).
  • 结构型(Structural):MVC、装饰模式(Decorator)、适配器模式(Adapter)和外观模式(Facade)。
  • 行为型(Bahavioral):观察者模式(Observer)、备忘录模式(Memento)

二、什么是MVC?

MVC,即Model-View-Controller。它是苹果公司官方推荐的App开发架构,也是一般开发者最先遇到,最经典的架构。它把整个App分为三个部分:Model负责处理数据;View负责处理UI;Controller是View和Model的桥梁,它将数据从Model层传送到View层并展示出来,同时将View层的交互传到Model层以改变数据。相比传统的MVC,苹果的MVC的特点是,Model层和View层是相互独立的。
由于Controller承担的任务相对较重,在实际开发中,很多初级开发者直接将View和Controller部分的代码全部塞到了ViewController类中,造成了它们的高度耦合。如何解耦View和Controller,在iOS开发中使一个热门的话题。

三、OC和Swift在单例模式的创建上有什么区别?

单例模式在创建过程中,要保证实例变量只被创建一次。在整个开发中需要特别注意线程安全,即使在多线程情况下,依然只初始化一次变量。
在OC中使用GCD来保证这一点的。示例代码如下:

+ (instanceType)sharedManager {
   static Manager *sharedManager = nil;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken,  ^{
        shareManager = [[Manager alloc] init];
    });
    return sharedManager;
}

在Swift中,let关键词已经保证了实例变量不会被修改,所以单例的创建就简单很多:

class Manager {
  static let shared = Manager()
  private init() {}
}

四、什么是装饰模式

装饰模式是在不改变原封装的前提下,为对象动态添加新功能的模式。在OC中,它的实现模式为Category和Delegation;在Swift中,它的实现形式为Extension和Delegation。

  • Category的好处之一是可以给类增加新的方法,它也可以利用动态特性增加新的变量。同时,Category的出现也减轻了类的负担,可以利用它将代码分散开。它的文件名形式一般为“类名+扩展名”。
  • Extension在Swift中的地位等同于Category在OC中的地位。它更强大的地方在于可以为Protocol扩展完成默认实现。
  • Delegation是程序中一个对象代表另一个对象,或者一个对象与另一个对象协同工作的模式,其一般配合protocol使用。例如tableView的UITableViewDataSource和UITableViewDelegate就是典型的Delegation模式。

注意,delegate一般被声明为weak,以防止循环引用。

五、什么是观察者模式(Observer)

观察者模式定义对象之间的一种一对多依赖关系,每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。在iOS开发中,典型的推模型实现方式为通知和KVO.
1.通知(Notifications)

  • 注册观察者Observer:通过NotificationCenter的addObserver:selector:name:object接口来注册对某一类型通知感兴趣。在注册时一定要注意,NotificationCenter不会对观察者进行引用计数+1的操作。
  • 通知中心NSNotificationCenter:通知的枢纽。
  • 被观察的对象:通过postNotificationName:object:userInfo:发送某一类型通知,广播改变。
  • 通知对象Notification:当有通知来的时候,通知中心会调用观察者注册的接口来广播通知,同时传递存储着要更改内容的Notification对象。

2.KVO
KVO,Key-Value Observer,即键值观察。它是一种没有通知中心的观察者模式的实现方式。一个主体对象管理所有依赖于它的观察者对象,并且在自身状态发生改变时主动通知观察者对象。KVO是一个纯OC的概念,Swift当前没有很好的动态机制,而且目前只有NSObject才支持KVO.它的具体实现步骤如下。
(1)注册观察者
(2)更改主题对象属性的值,即触发发送更改的通知。
(3)在制定的回调函数中,处理收到的更改通知。
在Swift 4中,我们不需要再手动的回收observer了。同时配合NSKeyValueObservation,我们可以更简单地使用KVO了,下面是示例代码:

// 在Swift4中,NSObject的类不再自动推断为@objc,需要用@objcMembers来声明其Objective-C特性
@objcMembers class User : NSObject {
    // dynamic关键词对observe的闭包来说是必需的
    dynamic var email : String
    
    init(email: String) {
        self.email = email
    }
    
    
}
let user = User(email:"user@hotmail.com")

// 注册观察email属性值,闭包中为若发生变化做出的相应处理
let observation = user.observe(\.email) {(user,change) in
    print("User's new email:\(user.email)")
}

user.email = "user@outlook.com"

六、什么是备忘录模式(Memento)

备忘录模式是一种保存对象当前的状态,并在日后可以恢复的模式。注意它不会破坏对象的封装,也就是说,私有对象也能保存下来。
备忘录模式最经典的使用方法就是用UserDefaults来读写,同时配合栈可以存储一系列状态。它经常用于初始化、重启、App前后台状态改变等场景。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容