单例模式在iOS开发中可能算是最常用的模式之一了,但是由于OC本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦. 今天就来说一说, 单例创建的方式和严谨的单例写法及可继承单例编写.
基本单例的创建方式
方式一(普通创建方式)
SingleHandle.h
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
SingleHandle.m
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
方式二(GCD 方式)
Singleton.h
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
Singleton.m
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
严谨的单例写法探究
一般写法
一般情况下,可能我们写的单例模式是上面的方式, 这里不再赘述, 但这样是不严谨的. 先来看一下到底不严谨的写法缺点是什么.
以上面的方式二举例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
打印结果:
single1 = < Singleton: 0x7ffb93743e80 >
single2 = < Singleton: 0x7ffb93743e80 >
single3 = < Singleton: 0x7ffb9373ecc0 >
-[Singleton copyWithZone:]: unrecognized selector sent to instance 0x7ffb9373ecc0
可以看到,当我们调用shareInstance方法时获取到的对象是相同的,但是当我们通过alloc和init来构造对象的时候,得到的对象却是不一样的。而且在 single4 这行注释打开后, 会在此崩溃, 原因如上.
所以,我们通过不同的途径得到不同的对象,显然是不行的。我们必须要确保对象的唯一性,所以我们就需要封锁用户通过alloc和init以及copy来构造对象这条道路。
我们知道,创建对象的步骤分为申请内存(alloc)、初始化(init)这两个步骤,我们要确保对象的唯一性,因此在第一步这个阶段我们就要拦截它。当我们调用alloc方法时,OC内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法中调用shareInstance方法返回单例对象,这样就可以达到我们的目的。拷贝对象也是同样的原理,覆写copyWithZone方法,然后在这个方法中调用shareInstance方法返回单例对象。
严谨的写法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
打印结果:
single1 = < Singleton: 0x7fe2e24a2880 >
single2 = < Singleton: 0x7fe2e24a2880 >
single3 = < Singleton: 0x7fe2e24a2880 >
single4 = < Singleton: 0x7fe2e24a2880 >
这样就是比较正确很严谨的写法了.
可继承单例探究
可继承单例是指父类中写下单例创建的方法, 当其本身类或其子类调用父类中的类创建的方法时, 可以各自类创建各自类的单例. 所以, 在父类中写的一个方法, 同时适用于其本身和其子类, 故称作可继承单例.
单例类 A :
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
单例类 B 和单例类 C 中无任何方法和属性, 只是继承于A类.
执行下面的方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
打印结果:
单例创建=====< A: 0x7fc21282fb60 >=====
单例创建=====< B: 0x7fc21282fcb0 >=====
单例创建=====< C: 0x7fc210427190 >=====
singleA = 0x7fc21282fb60
singleB = 0x7fc21282fcb0
singleC = 0x7fc210427190
singleA.a1 = aaa
singleB.a1 = bbb
singleC.a1 = ccc