单例模式
两种方式:
1.GCD方式
static id _instance;
+(instancetype)sharedPerson {
static dispatch_once_t onceToken;
// GCD dispatch_once, 本身是线程安全的,保证整个程序中只会执行一次
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
return _instance;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
(id)copyWithZone:(NSZone *)zone {
return _instance;
}(id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
2.加锁方式:
static id _instance;
+(instancetype)allocWithZone:(struct _NSZone *)zone {
//方案: 加互斥锁,解决多线程访问安全问题
@synchronized(self){
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
+(instancetype)sharedCar {
@synchronized(self){
if (_instance == nil) {
_instance = [[self alloc] init];
}
}
return _instance;
}
(id)copyWithZone:(NSZone *)zone {
return _instance;
}(id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
可以采用禁用方法:
+(instancetype) new attribute((unavailable("OneTimeClass类只能初始化一次")));
-(instancetype) copy attribute((unavailable("OneTimeClass类只能初始化一次")));
-(instancetype) mutableCopy attribute((unavailable("OneTimeClass类只能初始化一次")));
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)new NS_UNAVAILABLE;
- (id)copy NS_UNAVAILABLE; // 没有遵循协议可以不写
- (id)mutableCopy NS_UNAVAILABLE; // 没有遵循协议可以不写
优缺点:
优点:
(1)在整个程序中只会实例化一次,所以在程序如果出了问题,可以快速的定位问题所在;(2)由于在整个程序中只存在一个对象,节省了系统内存资源,提高了程序的运行效率;
缺点
(1)不能被继承,不能有子类;
(2)不易被重写或扩展(可以使用分类);
(3)同时,由于单例对象只要程序在运行中就会一直占用系统内存,该对象在闲置时并不能销毁,在闲置时也消耗了系统内存资源;
1:一个类只有一个对象,可能造成责任过重,在一定程度上违背了“单一职责原则”。
2:由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
3:滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。