Ensures a class has only one instance, and provide a global point of access to it.
『确保一个类有且只有一个实例,并提供一个全局点去访问它。』
---四人组(GoF)
一、设计模式
设计模式(Design pattern)从总体来说可以分为三大类:
创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式(7):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式(11):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
而我们iOS中常用的几种设计模式有:代理模式、观察者模式、MVC模式、单例模式、策略模式、工厂模式、MVVM。
今天我们共同探讨一下单例模式。其他几种设计模式有机会另行讨论。
二、什么是单例
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。
---百度百科
简而言之
- 1、它是一种常用的软件设计模式
- 2、程序运行过程,一个类只有一个实例,且该类可供外界访问,从而方便地控制实例个数,并节约系统资源
- 3、在整个应用程序中,共享一份资源
三、如何实现单例
根据前面对单例模式的定义我们知道,程序中必须能方便的控制一个类有且只有一个实例。且该类可供外界访问。
废话少说,上子弹。
- 1、用工厂方法创建对象,提供统一的创建方法给外部使用
+ (CYSingleTest *)sharedInstance
{
//为了隔离外部修改在sharedInstance中设置静态变量_instance
static CYSingleTest *_instance = nil;
//考虑多线程问题
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:nil];
});
return _instance;
- 2、控制一个类有且只有一个实例
CYSingleTest *singleTest0 = [CYSingleTest sharedInstance];
CYSingleTest *singleTest1 = [[CYSingleTest alloc] init];
CYSingleTest *singleTest2 = [CYSingleTest new];
以上是创建一个CYSingleTest实例的三种常用方式,我们打印一下看看结果:
singleTest0===<CYSingleTest: 0x6000021a8350>
singleTest1===<CYSingleTest: 0x6000021a84f0>
singleTest2===<CYSingleTest: 0x6000021a84e0>
通过结果我们发现上述三种方式实际上是创建了三个不同的实例,不满足要求,继续优化。
由Objective-C的一些特性可知,在创建对象的时候,无论是alloc还是new,都会调用以下方法。
+ (id)allocWithZone:(struct _NSZone *)zone
因此,可以重写这些方法,让创建的对象唯一。
+ (id)allocWithZone:(struct _NSZone *)zone
{
return [CYSingleTest sharedInstance];
}
我们再打印一下看看结果:
singleTest0===<CYSingleTest: 0x6000031c4340>
singleTest1===<CYSingleTest: 0x6000031c4340>
singleTest2===<CYSingleTest: 0x6000031c4340>
大功告成!
你以为故事到这里就告一段落了么?并没有!
除了上述三种创建对象的方式,我们常常还会用到copy和mutableCopy。
CYSingleTest *single3 = [single2 copy];
CYSingleTest *single4 = [single2 mutableCopy];
重点来了!
重点来了!
重点来了!
此时直接运行程序会报错:
-[CYSingleTest copyWithZone:]: unrecognized selector sent to instance 0x6000035c6da0
再由Objective-C的一些特性可知,在通过拷贝的方式创建对象时,会调用以下方法:
- (id)copyWithZone:(struct _NSZone *)zone
- (id)mutableCopyWithZone:(struct _NSZone *)zone
所以我们再重写两个拷贝方法:
- (id)copyWithZone:(struct _NSZone *)zone
{
return [CYSingleTest sharedInstance];
}
- (id)mutableCopyWithZone:(struct _NSZone *)zone
{
return [CYSingleTest sharedInstance];
}
注意:
//重写copy的相关方法时必须引入copy的相关文件
//表示该类遵守NSCopying、NSMutableCopying协议
@interface CYSingleTest : NSObject<NSCopying,NSMutableCopying>
我们最后打印一下看看结果:
singleTest0===<CYSingleTest: 0x600000388190>
singleTest1===<CYSingleTest: 0x600000388190>
singleTest2===<CYSingleTest: 0x600000388190>
singleTest3===<CYSingleTest: 0x600000388190>
singleTest4===<CYSingleTest: 0x600000388190>
OK,打完收工!
四、总结
一个项目往往不止一个单例,所以我们可以将以上方法整理成宏定义或者代码块,这样我们以后使用的时候就会更加得心应手。具体操作这里就不再赘述了。
网友评论