多线程11——单例设计模式
一、说明
种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
二、ARC下的单例模式
由于不是我们自己管理内存,所以不用考虑释放的问题。这种情况下,我们创建一个类方法,让外界获取我们的实例对象。然后重写我们创建实例的方法
我们创建的单例如下
2.1 SingleArc
2.1.1 SingleArc.h
//
// SingleArc.h
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SingleArc : NSObject
/*外部获取实例的方法*/
+(instancetype)shareSingle;
@end
2.1.2 SingleArc.m
//
// SingleArc.m
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
// 自动管理的 单例模式
//
#import "SingleArc.h"
@implementation SingleArc
static SingleArc *_instance;
+(instancetype)allocWithZone:(struct _NSZone *)zone{
// //考虑线程安全可以使用互斥锁
// @synchronized (self) {
// if(_instance==nil){
// _instance = [super allocWithZone:zone];
// }
// }
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
+(instancetype)shareSingle{
return [[self alloc]init];
}
-(id)copyWithZone:(NSZone*)zone{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone*)zone{
return _instance;
}
@end
2.2 代码示例
/*ARC 单例模式测试*/
-(void)singleArcTest{
SingleArc *s1 = [[SingleArc alloc]init];
SingleArc *s2 = [[SingleArc alloc]init];
SingleArc *s3 = [SingleArc new];
SingleArc *s4 = [SingleArc shareSingle];
SingleArc *s5 = [s1 copy];
SingleArc *s6 = [s2 mutableCopy];
NSLog(@"s1 -- %@",s1);
NSLog(@"s2 -- %@",s2);
NSLog(@"s3 -- %@",s3);
NSLog(@"s4 -- %@",s4);
NSLog(@"s5 -- %@",s5);
NSLog(@"s6 -- %@",s6);
}
2.3 运行结果
[20863:94340] s1 -- <SingleArc: 0x608000007a20>
[20863:94340] s2 -- <SingleArc: 0x608000007a20>
[20863:94340] s3 -- <SingleArc: 0x608000007a20>
[20863:94340] s4 -- <SingleArc: 0x608000007a20>
[20863:94340] s5 -- <SingleArc: 0x608000007a20>
[20863:94340] s6 -- <SingleArc: 0x608000007a20>
我们可以看到我们所有的对象都是同一个。
二、ARC和MRC切换
四、MRC下的单例模式
由于使我们自己管理内存,这里面我们会调用 release
等方法。这样我们创建的实例被释放了,接下来我们就不能用了,因此我们在MRC下需要重写这些方法
4.1 SingleMrc
4.1.1 SingleMrc.h
//
// SingleMrc.h
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SingleMrc : NSObject
+(instancetype)shareSingleMrc;
@end
4.1.2 SingleMrc.m
//
// SingleMrc.m
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
// 手动管理的 单例模式
#import "SingleMrc.h"
@implementation SingleMrc
static SingleMrc *_instance;
/*重写创建实例的方法*/
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
+(instancetype)shareSingleMrc{
return [[SingleMrc alloc]init];
}
-(id)copyWithZone:(NSZone*)zone{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone*)zone{
return _instance;
}
//MRC方式下,我们得重写下面的方法
-(oneway void)release{
}
-(instancetype)retain{
return _instance;
}
/*引用计数器设置为最大值*/
-(NSUInteger)retainCount{
return MAXFLOAT;
}
@end
4.2 代码示例
/*MRC 单例模式测试*/
-(void)singleMrcTest{
SingleMrc *s1 = [[SingleMrc alloc]init];
[s1 release];
SingleMrc *s2 = [[SingleMrc alloc]init];
[s1 release];
SingleMrc *s3 = [SingleMrc new];
[s1 release];
SingleMrc *s4 = [SingleMrc shareSingleMrc];
[s1 release];
SingleMrc *s5 = [s1 copy];
[s1 release];
SingleMrc *s6 = [s2 mutableCopy];
[s1 release];
NSLog(@"s1 -- %@",s1);
NSLog(@"s2 -- %@",s2);
NSLog(@"s3 -- %@",s3);
NSLog(@"s4 -- %@",s4);
NSLog(@"s5 -- %@",s5);
NSLog(@"s6 -- %@",s6);
}
4.3 运行结果
[28259:136270] s1 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s2 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s3 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s4 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s5 -- <SingleMrc: 0x60000001a8f0>
[28259:136270] s6 -- <SingleMrc: 0x60000001a8f0>
五、ARC和MRC都能使用的单例模式
这二者的区别就是要不要重写以下的方法
-(oneway void)release;
-(instancetype)retain;
-(NSUInteger)retainCount;
那么我们的操作也是非常简单,只需要判断是 ARC 还是 MRC ,MRC下我们重写这些方法。
那么怎么判断呢?
我们可以使用以下的代码判断
#if __has_feature(objc_arc)
//ARC
#else
//MRC
#elseif
5.1 SingleAMrc
5.1.1 SingleAMrc.h
//
// SingleAMrc.h
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SingleAMrc : NSObject
+(instancetype)shareSingleAMrc;
@end
5.1.2 SingleAMrc.m
//
// SingleAMrc.m
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import "SingleAMrc.h"
@implementation SingleAMrc
//-----------下面这部分是ARC和MRC都是共有的------------
static SingleAMrc *_instance;
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
+(instancetype)shareSingleAMrc{
return _instance;
}
-(id)copyWithZone:(NSZone*)zone{
return _instance;
}
-(id)mutableCopyWithZone:(NSZone*)zone{
return _instance;
}
//----------下面这部分是MRC特有的------------
//编译判断,如果是MRC我们才去操作
#if __has_feature(objc_arc)//如果是ARC不操作
//ARM
#else//如果是MRC重写我们的方法
//MRC
-(oneway void)release{
}
-(instancetype)retain{
return _instance;
}
-(NSUInteger)retainCount{
return MAXFLOAT;
}
#endif
@end
5.2 代码示例
我们的测试实在 MRC 下的
/*ARC和MRC都行的 单例模式测试*/
-(void)singleAMrcTest{
SingleAMrc *s1 = [[SingleAMrc alloc]init];
[s1 release];
SingleAMrc *s2 = [[SingleAMrc alloc]init];
[s2 release];
SingleAMrc *s3 = [SingleAMrc new];
[s3 release];
SingleAMrc *s4 = [SingleAMrc shareSingleAMrc];
[s4 release];
SingleAMrc *s5 = [s1 copy];
[s5 release];
SingleAMrc *s6 = [s2 mutableCopy];
[s6 release];
NSLog(@"s1 -- %@",s1);
NSLog(@"s2 -- %@",s2);
NSLog(@"s3 -- %@",s3);
NSLog(@"s4 -- %@",s4);
NSLog(@"s5 -- %@",s5);
NSLog(@"s6 -- %@",s6);
}
5.3 运行结果
[29747:143162] s1 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s2 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s3 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s4 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s5 -- <SingleAMrc: 0x6000000010b0>
[29747:143162] s6 -- <SingleAMrc: 0x6000000010b0>
六、宏定义单例模式模板
如果我们想要创建多个类的单例模式,那么我们发现代码基本是一样的,最多就是类的名字不一样。那么我们可以不可以简单点来实现呢??
我们可以定义宏来实现,宏之间的连接符使用
/
参数拼接使用
##
那么我们在定义我们的内部静态变量的时候怎么弄呢?
我们可以使用id
如下
static SingleAMrc *_instance;
可以改为
static id _instance;
我们获取实例的方法,方法名的后半部分是不一样的,那么我们怎么解决呢?
我们可以使用宏传递参数过来,然后拼接
如下
+(instancetype)shareSingleAMrc;
可以改为
#define SingleH(name) +(instancetype)share##name;
那么我们怎么解决ARC和MRC呢?
我们可以在判断里面重写代码
如下
#if
//ARC下的方法
#else
//MRC下的方法
#elseif
6.1 Single.h 宏定义的头文件
//
// Single.h
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
#define SingleH(name) +(instancetype)share##name;
#if __has_feature(objc_arc)
//ARC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}
#else
//MRC
#define SingleM(name) static id _instance;\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instance = [super allocWithZone:zone];\
});\
\
return _instance;\
}\
\
+(instancetype)share##name\
{\
return [[self alloc]init];\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
\
-(id)mutableCopyWithZone:(NSZone *)zone\
{\
return _instance;\
}\
-(oneway void)release\
{\
}\
\
-(instancetype)retain\
{\
return _instance;\
}\
\
-(NSUInteger)retainCount\
{\
return MAXFLOAT;\
}
#endif
6.2 使用宏定义Single.h创建工具类QWMTool
6.2.1 QWMTool.h
//
// QWMTool.h
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import <Foundation/Foundation.h>
#include "Single.h"
@interface QWMTool : NSObject
SingleH(Tool)
@end
6.2.1 QWMTool.m
//
// QWMTool.m
// 03_UIview84多线程_单例模式
//
// Created by 杞文明 on 17/9/3.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import "QWMTool.h"
@implementation QWMTool
SingleM(Tool)
@end
6.3 QWMTool示例代码
ARC下测试的
/* 宏定义的单例模式测试*/
-(void)qwmtoolTest{
QWMTool *t1 = [[QWMTool alloc]init];
QWMTool *t2 = [[QWMTool alloc]init];
QWMTool *t3 = [QWMTool new];
QWMTool *t4 = [QWMTool shareTool];
QWMTool *t5 = [t1 copy];
QWMTool *t6 = [t2 mutableCopy];
NSLog(@"t1 -- %@",t1);
NSLog(@"t2 -- %@",t2);
NSLog(@"t3 -- %@",t3);
NSLog(@"t4 -- %@",t4);
NSLog(@"t5 -- %@",t5);
NSLog(@"t6 -- %@",t6);
}
6.4 QWMTool测试运行结果
[32260:152900] t1 -- <QWMTool: 0x608000017680>
[32260:152900] t2 -- <QWMTool: 0x608000017680>
[32260:152900] t3 -- <QWMTool: 0x608000017680>
[32260:152900] t4 -- <QWMTool: 0x608000017680>
[32260:152900] t5 -- <QWMTool: 0x608000017680>
[32260:152900] t6 -- <QWMTool: 0x608000017680>