概述
单例在不同的语言当中可能定义可能不一定完全相同,但宗旨应该是一样的:该类在程序运行期间有且仅有一个实例
所以,在使用单例的时候要考虑好自己的需求是否真的需要,过度使用是不好的
1.单例的优点(主要优点)
单例可以保证系统中该类有且仅有一个实例,所以很便于外界访问.
因为其上面的特点,对于项目中的个别场景的传值,存储状态等等更加方便
2.单例的缺点(主要缺点)
单例实例一旦创建,对象指针是保存在静态区的,那么在堆区分配空间只有在应用程序终止后才会被释放
单例不能继承
单例的实现(所有的代码实现都是基于ARC模式下)
- 单例的实现重点就是防止在外部调用的时候出现多个不同的实例,也就是说我们要从创建的方式入手禁止出现多个不同的实例
相信大家都知道经常出现错误的就是在不知情的情况下掉用的系统的一些初始化方法, 如果是自己手误那就知道怎么说你了哈哈,如果其他人使用你创建的类不看对外接口 那这个队友还是需要有待提高的(前提是你要写的清楚写注释)
个人观点主要是做到以下几点:
防止调用 alloc]init]引起的错误
防止调用 new 引起的错误
防止调用 copy 引起的错误(应该不常用)
防止调用 mutableCopy 引起的错误(应该不常用)
实现方法一
首先需要使用GCD来实现的单例创建,为啥使用GCD请自行学习
- 第一步 (必不可少的)
+ (instancetype)sharedSingleton {
static Singleton *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//不能再使用alloc方法
//因为已经重写了allocWithZone方法,所以这里要调用父类的分配空间的方法
_sharedSingleton = [[super allocWithZone:NULL] init];
});
return _sharedSingleton;
}
-
第二步
防止alloc] init] 和new引起的错误,因为alloc] init] 和 new 实际是一样的工作原理.都是执行了下面方法
// 防止外部调用alloc 或者 new
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [Singleton sharedSingleton];
}
-
第三步 NSCopying
防止copy引起的错误,个人感觉当你的单例类不遵循NSCopying协议,外部调用本身就会出错. 如果不是业务需求不遵循协议,该方法也可以不写这都是个人观点 不过为了严谨还是写吧
// 防止外部调用copy
- (id)copyWithZone:(nullable NSZone *)zone {
return [Singleton sharedSingleton];
}
-
第四步
防止mutableCopy引起的错误,个人感觉当你的单例类不遵循NSMutableCopying协议,外部调用本身就会出错. 如果不是业务需求不遵循协议,该方法也可以不写这都是个人观点 不过为了严谨还是写吧
// 防止外部调用mutableCopy
- (id)mutableCopyWithZone:(nullable NSZone *)zone {
return [Singleton sharedSingleton];
}
实现方法二
上面的方法是把其可能出现的初始化方法做了相应的处理来其保证安全性
其实我们可以在不做处理的情况下 禁止外部调用岂不是更简单 个人感觉该方法也很不错而且一些成熟的第三方中的单例中也有使用该方法的
直接在你创建的单例文件的.h文件中加入代码
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (id)copy NS_UNAVAILABLE; // 没有遵循协议可以不写
- (id)mutableCopy NS_UNAVAILABLE; // 没有遵循协议可以不写
.m文件实现一个方法即可,上面方式的其他方法就不要写了
// 跟上面的方法实现有一点不同
+ (instancetype)sharedSingleton {
static Singleton *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 要使用self来调用
_sharedSingleton = [[self alloc] init];
});
return _sharedSingleton;
}
以上的运行结果可以自行测试
其实单例的写法的重点以及理解 都是考察对内存的分配的认识. (本人能力有限还需学习)
以上的都是个人总结,也许有不对或者不妥当的地方,也希望大家指正