回顾单例模式

单例模式

[toc]

创建对象

首先创建一个对象,我们看看他的地址。
打印地址要用取地址符”&”

1
2
3
4
5
6
7
8
9
10
SingleObject *obj = [[SingleObject alloc]init];
SingleObject *obj2 = [SingleObject copy];
SingleObject *obj3 = [SingleObject new];

NSLog(@"==================");
NSLog(@"%p",&obj);
NSLog(@"==================");
NSLog(@"%p",&obj2);
NSLog(@"==================");
NSLog(@"%p",&obj3);

打印出来我们看到地址是

1
2
3
4
5
6
==================
0x7ffeed9b2868
==================
0x7ffeed9b2860
==================
0x7ffeed9b2858

实际上当我们使用new、alloc、copy来创建一个对象时,他分配的地址都是不一样的。
这样的话就导致我们在开发中可能要调用对象中的一个方法,但是我们就要创建对象,系统就需要给他分配一个内存空间,这样就比较占内存了。这时我们就可以使用单例来实现节省内存。

单例

单例是什么呢?单例就是在应用程序中有且只有一个对象实例。不管你怎么创建,他的地址都是不会改变的,地址不改变,就说明他只有一个内存空间。
这样的话我们调用实例方法很省事了。但是使用单例也是要看情况的,不能盲目使用。

1.单例的优点(主要优点)
单例可以保证系统中该类有且仅有一个实例,所以很便于外界访问.
因为其上面的特点,对于项目中的个别场景的传值,存储状态等等更加方便
2.单例的缺点(主要缺点)
单例实例一旦创建,对象指针是保存在静态区的,那么在堆区分配空间只有在应用程序终止后才会被释放
单例不能继承

有两种方法实现单例

方法一

第一步

初始化创建对象实例的方法

1
2
3
4
5
6
7
8
9
10
+ (instancetype)sharedSingleton {
static SingleObject *sharetInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//不能再使用alloc方法
//因为已经重写了allocWithZone方法,所以这里要调用父类的分配空间的方法
sharetInstance = [[super allocWithZone:NULL] init];
});
return sharetInstance;
}
第二步

初始化alloc] init] 和new引起的错误,因为alloc] init] 和 new 实际是一样的工作原理.都是执行了下面方法

1
2
3
4
// 防止外部调用alloc 或者 new
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [Singleton sharedSingleton];
}
第三步 NSCopying

防止copy引起的错误,个人感觉当你的单例类不遵循NSCopying协议,外部调用本身就会出错. 如果不是业务需求不遵循协议,该方法也可以不写 这都是个人观点 不过为了严谨还是写吧

1
2
3
4
// 防止外部调用copy
- (id)copyWithZone:(nullable NSZone *)zone {
return [Singleton sharedSingleton];
}
第四步

防止mutableCopy引起的错误,个人感觉当你的单例类不遵循NSMutableCopying协议,外部调用本身就会出错. 如果不是业务需求不遵循协议,该方法也可以不写 这都是个人观点 不过为了严谨还是写吧

1
2
3
4
// 防止外部调用mutableCopy
- (id)mutableCopyWithZone:(nullable NSZone *)zone {
return [Singleton sharedSingleton];
}

实现方法二

上面的方法是把其可能出现的初始化方法做了相应的处理来其保证安全性
其实我们可以在不做处理的情况下 禁止外部调用岂不是更简单 个人感觉该方法也很不错而且一些成熟的第三方中的单例中也有使用该方法的
直接在你创建的单例文件的.h文件中加入代码

1
2
3
4
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (id)copy NS_UNAVAILABLE; // 没有遵循协议可以不写
- (id)mutableCopy NS_UNAVAILABLE; // 没有遵循协议可以不写

.m文件实现一个方法即可,上面方式的其他方法就不要写了

1
2
3
4
5
6
7
8
9
10
// 跟上面的方法实现有一点不同
+ (instancetype)sharedSingleton {
static Singleton *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 要使用self来调用
_sharedSingleton = [[self alloc] init];
});
return _sharedSingleton;
}

最后用方法一来测试一下代码

1
2
3
4
5
6
7
8
9
SingleObject *obj = [SingleObject sharedSingleton];
SingleObject *obj1 = [[SingleObject alloc]init];
SingleObject *obj2 = [[SingleObject alloc] copy];
SingleObject *obj3 = [SingleObject new];

NSLog(@"%p",&obj);
NSLog(@"%p",&obj1);
NSLog(@"%p",&obj2);
NSLog(@"%p",&obj3);

9CE8803E-FAD7-47F2-A3A6-BDBC5518FA43

-------------本文结束感谢您的阅读-------------