ARC(自动内存管理)下实现单例模式###前言开发过程中,遇到一种情况:需要多次用到某个类,每次创建都会分配新的内存地址。但是,在某些场合这是没有必要的。>如播放音乐,一般不会说,开一个播放器同时播放多首歌。而且,系统的资源是有限的,特别是移动设备。所以 ‘ 单例模式 ’ 应运而生。###简介单例模式:在程序运行过程中,一个类只有一个实例。而且该实例易于供外界使用。换句话说,一个类无论创建多少次,都只分配一次存储空间。###目的为了在程序运行过程中,共享一份资源,且这份资源只会初始化一次,只分配一次存储空间,从而节约系统资源。###好处节约系统资源。###实现步骤以PDuser类为例1、定义静态变量,存储唯一实例```static PDuser *_instance;```这样,外面就不能获取到这个实例变量,只能在本文件中访问。2、重写`allocWithZone `方法,在里面用一次性代码函数`dispatch_once `,并调用`super allocWithZone`方法```+ (instancetype)allocWithZone:(struct _NSZone *)zone{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance;}```这一步,也可以用懒加载的方式来做:```+ (instancetype)allocWithZone:(struct _NSZone *)zone{ // 考虑到使用时可能在多条线程同时执行此方法任务,那么就可能引发线程安全问题,所以需要对线程进行加锁操作 @synchronized(self) { if (_instance == nil) { _instance = [super allocWithZone:zone]; } } return _instance;}```3、实现类方法```+(instancetype)shareUser{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance;}```> new方法:分配内存并且初始化alloc:为对象分配内存,init:初始化对象中的属性等4、外界调用方法提供一个类方法,获取单例对象,方便创建。`+ (instancetype)shareUser;`至此,基本的单例已经实现。下面可以再继续完善。***5、处理copy的情况(可选)为了让单例严谨一点,如果要支持copy,则重写copy和mutableCopy。直接返回变量即可,因为只有创建了对象,才能使用copy方法。> 先遵守协议```
- (id)copyWithZone:(NSZone *)zone
{
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return _instance;
}
```
- 注意 : 使用单例模式设计的类,不可继承!
###单例命名格式
牵扯到命名的问题,怎样命名才规范?单例常见的命名形式有这几种:share 、share + 类名 、default、default + 类名
###适用场景
在整个程序中,都可以共享同一份资源——这份资源只需创建初始化一次,只分配一次存储空间即可。
例如:用户实例、文件管理者等。
###测试
创建3个对象
```
PDuser *user1 = [PDuser shareUser];
PDuser *user2 = [PDuser shareUser];
PDuser *user3 = [PDuser shareUser];
NSLog(@"user1:%@\nuser2:%@\nuser3:%@",user1,user2,user3);
```
结果
![QQ.png](https://img.haomeiwen.com/i6430368/48dc928ee23a810f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
成功
###宏定义
若要实现单例代码复用,不能用继承。用宏,把单例模式抽取出来。
新建一个.h文件Single.h,其中包含两个部分,即.h和.m部分
把具体的类类型,改成id 类型,并设置参数(name)类名,用##连接,使用时,外界的类可以灵活变换。另外,.m中的代码用多个"\"号连接起来。
![QQ.png](https://img.haomeiwen.com/i6430368/83573128ed310b49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
外界使用:
在新建的某个类的.h中,注意带上参数 类名
![QQ.png](https://img.haomeiwen.com/i6430368/379e794d5696bdda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
.m中
![QQ.png](https://img.haomeiwen.com/i6430368/79fda8f844b47d5a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
即可
###相关资料
https://www.jianshu.com/p/5226bc8ed784
网友评论