ios单例模式
一、什么是单例模式
官方解释:
保证一个类只有一个实例,并且提供一个全局的访问入口访问这个实例。
一个类必须只有一个对象。客户端必须通过一个众所周知的入口访问这个对象。
这个唯一的对象需要扩展的时候,只能通过子类化的方式。客户端的代码能够不需要任何修改就能够使用扩展后的对象。
初读是不是一头雾水,emm,我也是,呐,看完单例模式的用处再跟你解释。
二、单例模式的用处
主要用在封装网络请求,播放器,存放常用数据等。
仔细想想,你做网络请求时如果不是用单例模式,是不是每次网络请求时都要alloc个对象,然后调用方法请求?拜托,你alloc多了系统资源被占用过多,性能低下,我靠,那还开发个屁,所以这个时候单例模式就能很好的帮助我们解决这个问题,故你可以这样来看待单例模式:
单例在整个工程中,就相当于一个全局变量,就是不论在哪里需要用到这个类的实例变量,都可以通过单例方法来取得,而且一旦你创建了一个单例类,不论你在多少个界面中初始化调用了这个单例方法取得对象,它们所有的对象都是指向的同一块内存存储空间(即单例类保证了该类的实力对象是唯一存在的一个)。
注意加粗和斜体字体哦,多读几遍!!!!
三、那如何使用单例模式呢?
+ (DJSingleton *)shareInstance{
static DJSingleton * s_instance_dj_singleton = nil ;//设置静态变量,隔离外部修改
if (s_instance_dj_singleton == nil) {
s_instance_dj_singleton = [[DJSingleton alloc] init];
}
return (DJSingleton *)s_instance_dj_singleton;
}
四、可是多线程情况下呢?
+ (DJSingleton *)shareInstance{
static DJSingleton * s_instance_dj_singleton = nil ;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (s_instance_dj_manager == nil) {
s_instance_dj_manager = [[DJSingleton alloc] init];
}
});
return (DJSingleton *)s_instance_dj_singleton;
}
五、那再调用alloc呢?
看起来很完美了。可是Objective-C毕竟是Objective-C。别的语言,诸如C++,java,构造方法可以隐藏。Objective-C中的方法,实际上都是公开的,虽然我们提供了一个方便的工厂方法的访问入口,但是里面的alloc方法依旧是可见的,可以调用到的。也就是说,虽然你给了我一个工厂方法,调皮的小伙伴可能依旧会使用alloc的方式创建对象。这样会导致外面使用的时候,依旧可能创建多个实例。
关于这个事情的处理,可以分为两派。一个是冷酷派,技术上实现无论你怎么调用,我都给你同一个单例对象;一个是温柔派,是从编译器上给调皮的小伙伴提示,你不能这么造对象,温柔的指出有问题,但不强制约束。
1. 冷酷派的实现
冷酷派的实现从OC的对象创建角度出发,就是把创建对象的各种入口给封死了。alloc,copy等等,无论是采用哪种方式创建,我都保证给出的对象是同一个。
由Objective-C的一些特性可以知道,在对象创建的时候,无论是alloc还是new,都会调用到 allocWithZone方法。在通过拷贝的时候创建对象时,会调用到-(id)copyWithZone:(NSZone *)zone,-(id)mutableCopyWithZone:(NSZone *)zone方法。因此,可以重写这些方法,让创建的对象唯一
+(id)allocWithZone:(NSZone *)zone{
return [DJSingleton sharedInstance];
}
+(DJSingleton *) sharedInstance{
static DJSingleton * s_instance_dj_singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
s_instance_dj_singleton = [[super allocWithZone:nil] init];
});
return s_instance_dj_singleton;
}
-(id)copyWithZone:(NSZone *)zone{
return [DJSingleton sharedInstance];
}
-(id)mutableCopyWithZone:(NSZone *)zone{
return [DJSingleton sharedInstance];
}
2. 温柔派的实现
温柔派就直接告诉外面,alloc,new,copy,mutableCopy方法不可以直接调用。否则编译不过。
+(instancetype) alloc __attribute__((unavailable("call sharedInstance instead")));
+(instancetype) new __attribute__((unavailable("call sharedInstance instead")));
-(instancetype) copy __attribute__((unavailable("call sharedInstance instead")));
-(instancetype) mutableCopy __attribute__((unavailable("call sharedInstance instead")));
六、最后
这里有两篇比较好文章,同时本篇内容也摘抄了其中。