什么是单例模式?
一个单例类,在整个程序中只有一个实例,并且提供一个类方法供全局调用,在编译时初始化这个类,然后一直保存在内存中,到程序(APP)退出时由系统自动释放这部分内存。
系统提供的单例类
UIApplication(应用程序实例类)
NSNotificationCenter(消息中心类)
NSFileManager(文件管理类)
NSUserDefaults(应用程序设置)
NSURLCache(请求缓存类)
NSHTTPCookieStorage(应用程序cookies池)
什么时候选择单例模式?
一个类只有一个实例对象时
如何实现?
需要补充的点
dispatch_once 无论使用多线程还是单线程,都只执行一次, 在安全的前提下也保证了性能, 是官方推荐的实现单例方式.
- dispatch_once 主要是根据onceToken 的值来决定怎么去执行代码。
1.当onceToken=0时,线程执行dispatch_once的block中代码
2.当onceToken=-1时,线程跳过dispatch_once的block中代码不执行
3.当onceToken为其他值时,线程被阻塞,等待onceToken值改变- dispatch_once 执行的流程
1.当线程调用shareInstance,此时onceToken = 0,调用block中的代码。 此时onceToken的值变为其他值。
2.当其他线程再调用shareInstance方法时,onceToken的值已经是其他值了,线程阻塞。
3.当block线程执行完block之后,onceToken变为-1.其他线程不再阻塞,跳过block。
4.下次再调用shareInstance时,block已经为-1.直接跳过block。
- 创建一个类,继承于NSObject
声明一个类方法,允许程序通过该方法获取该类的唯一实例。
但如果是用alloc、copy方法依然会创建多个实例。
在对象创建的时候,无论是alloc还是new,都会调用到 allocWithZone方法。在通过拷贝的时候创建对象时,会调用到-(id)copyWithZone:(NSZone *)zone,-(id)mutableCopyWithZone:(NSZone *)zone方法。因此,可以重写这些方法,让创建的对象唯一。
@interface Singleton : NSObject
+ (Singleton *)shareInstance;
@end
#import "Singleton.h"
@implementation Singleton
static Singleton *singleton = nil;
+ (Singleton *)shareInstance {
static dispatch_once_t oncetoken;
dispatch_once(&oncetoken, ^{
singleton = [[super allocWithZone:nil] init];
});
return singleton;
}
+ (id)allocWithZone:(struct _NSZone *)zone {
return singleton;
}
- (id)copyWithZone:(NSZone *)zone{
return singleton;
}
- (id)mutableCopyWithZone:(NSZone *)zone{
return singleton;
}
@end
创建一个实例,使用alloc、copy等方法,打印查看地址
#import "ViewController.h"
#import "Singleton.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Singleton *a = [Singleton shareInstance];
Singleton *b = [Singleton shareInstance];
Singleton *c = [[Singleton alloc] init];
Singleton *d = [a copy];
Singleton *e = [b mutableCopy];
NSLog(@"%@, %@, %@, %@, %@", a, b, c, d, e);
}
@end
打印结果如下:
参考文章:
http://www.cocoachina.com/articles/21300
https://www.jianshu.com/p/9165a6de227e