【单例模式】单例模式 & GCD单例模式 & 将封装单例模式到宏
懒汉式单例模式
下面的代码块, 基本是单例模式的完整版本了.
可扩展的地方,可以在init方法中作扩展.
1 // static 在全局变量的作用域仅限于当前文件内部 2 static id _instance; 3 4 /** 5 * alloc方法内部会调用这个方法 , zone是代表内存块的意思 6 */ 7 + (id)allocWithZone:(struct _NSZone *)zone 8 { 9 // 首先判断防止频繁加锁 , 如果不判断,每次进来先加锁在判断 10 if (_instance == nil) { 11 // 只有第一次为空得时候才进来, 然后加锁. 必须加锁, 防止多线程同时操作同一变量 12 @synchronized(self) { 13 // 某条线程进来之后, 首先判断变量是否为空,如果为空,才执行下面语句 14 if (_instance == nil) { 15 // 内部默认做法,调用父类方法分配内存空间 16 _instance = [super allocWithZone:zone]; 17 } 18 } 19 } 20 21 // 直接返回对象 22 return _instance; 23 } 24 25 /** 26 * 单例模式应该实现一个方法,让别人调用创建,并且创建无数次都应该是同一个对象 27 * 28 */ 29 + (instancetype)sharedTool 30 { 31 if (_instance == nil) { // 防止频繁加锁 32 @synchronized(self) { 33 if (_instance == nil) { // 防止创建多次 34 // alloc 又会调用上面的allocWithZone方法 35 _instance = [[self alloc] init]; 36 } 37 } 38 } 39 return _instance; 40 } 41 42 // 应该提供该方法, 防止以后别人需要用copy得时候,也保证创建出来的对象是同一对象 43 - (id)copyWithZone:(NSZone *)zone 44 { 45 return _instance; 46 }
GCD 单例模式
// 用来保存唯一的单例对象, 同样也要加上static,防止别人能修改该字段 static id _instace; /** * */ + (id)allocWithZone:(struct _NSZone *)zone { /** * dispatch_once只会执行一次,而且内部自动封装了锁,更简便安全 */ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instace = [super allocWithZone:zone]; }); return _instace; } + (instancetype)sharedDataTool { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instace = [[self alloc] init]; }); return _instace; } /** * 防止Copy创建对象 */ - (id)copyWithZone:(NSZone *)zone { return _instace; }
宏实现单例
新建一个.h文件,将下列代码复制进去.即可生成一个单例模式文件
1 // .h文件 2 #define HMSingletonH(name) + (instancetype)shared##name; 3 4 // .m文件 5 #if __has_feature(objc_arc) 6 7 #define HMSingletonM(name) \ 8 static id _instace; \ 9 \ 10 + (id)allocWithZone:(struct _NSZone *)zone \ 11 { \ 12 static dispatch_once_t onceToken; \ 13 dispatch_once(&onceToken, ^{ \ 14 _instace = [super allocWithZone:zone]; \ 15 }); \ 16 return _instace; \ 17 } \ 18 \ 19 + (instancetype)shared##name \ 20 { \ 21 static dispatch_once_t onceToken; \ 22 dispatch_once(&onceToken, ^{ \ 23 _instace = [[self alloc] init]; \ 24 }); \ 25 return _instace; \ 26 } \ 27 \ 28 - (id)copyWithZone:(NSZone *)zone \ 29 { \ 30 return _instace; \ 31 } 32 33 #else 34 35 #define HMSingletonM(name) \ 36 static id _instace; \ 37 \ 38 + (id)allocWithZone:(struct _NSZone *)zone \ 39 { \ 40 static dispatch_once_t onceToken; \ 41 dispatch_once(&onceToken, ^{ \ 42 _instace = [super allocWithZone:zone]; \ 43 }); \ 44 return _instace; \ 45 } \ 46 \ 47 + (instancetype)shared##name \ 48 { \ 49 static dispatch_once_t onceToken; \ 50 dispatch_once(&onceToken, ^{ \ 51 _instace = [[self alloc] init]; \ 52 }); \ 53 return _instace; \ 54 } \ 55 \ 56 - (id)copyWithZone:(NSZone *)zone \ 57 { \ 58 return _instace; \ 59 } \ 60 \ 61 - (oneway void)release { } \ 62 - (id)retain { return self; } \ 63 - (NSUInteger)retainCount { return 1;} \ 64 - (id)autorelease { return self;} 65 66 #endif
以上三种都是可运用的单例模式
单例模式是什么?
-> 单例模式是确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类
单例模式的作用?
-> 可以保证在程序运行过程, 一个类只有一个实例,而且该实例易于供外界访问,从而方便地控制了实例的个数,并节约系统资源
单例模式的使用场合?
-> 整个应用程序中, 共享一份资源,或者这份资源只需要创建初始化1次.
例如 : 一些工具类,(使用到项目各个地方,并且一般只有一份.)
: 例如一个注册的页面, 点击注册跳到注册页面.但是如果这个时候,再点击注册,我们希望一般都是进到同一个注册的页面,所以,这里应该就使用单例模式.