博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
单例模式——使用GCD实现单例模式 & 非ARC单例模式 &使用GCD和线程锁实现单例模式-b...
阅读量:1545 次
发布时间:2019-04-21

本文共 6548 字,大约阅读时间需要 21 分钟。

1.单利模式概述

 链接:  

2.使用GCD实现单利模式

2.1新建一个project,然后新建一个HMDataTool类展示GCD实现单例模式

 

[objc]   
 
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface HMDataTool : NSObject  
  4. + (instancetype)sharedDataTool;  
  5. @end  

 

[objc]   
 
  1. #import "HMDataTool.h"  
  2.   
  3. @implementation HMDataTool  
  4. // 用来保存唯一的单例对象  
  5. static id _instace;  
  6.   
  7. + (id)allocWithZone:(struct _NSZone *)zone  
  8. {  
  9.     static dispatch_once_t onceToken;  
  10.     dispatch_once(&onceToken, ^{   //onceToken是GCD用来记录是否执行过 ,如果已经执行过就不再执行(保证执行一次)  
  11.         _instace = [super allocWithZone:zone];  
  12.     });  
  13.     return _instace;  
  14. }  
  15.   
  16. + (instancetype)sharedDataTool  
  17. {  
  18.     static dispatch_once_t onceToken;  
  19.     dispatch_once(&onceToken, ^{  
  20.         _instace = [[self alloc] init];  
  21.     });  
  22.     return _instace;  
  23. }  
  24.   
  25. - (id)copyWithZone:(NSZone *)zone  
  26. {  
  27.     return _instace;  
  28. }  
  29.   
  30. @end  

 

[objc]   
 
  1. #import "htingViewController.h"  
  2. #import"HMDataTool.h"  
  3. @interface htingViewController ()  
  4.   
  5. @end  
  6.   
  7. @implementation htingViewController  
  8.   
  9. - (void)viewDidLoad  
  10. {  
  11.     [super viewDidLoad];  
  12.     // Do any additional setup after loading the view, typically from a nib.  
  13.       
  14.         HMDataTool *tool1 = [HMDataTool sharedDataTool];  
  15.         HMDataTool *tool2 = [HMDataTool sharedDataTool];  
  16.         HMDataTool *tool3 = [[HMDataTool alloc] init];  
  17.         HMDataTool *tool4 = [[HMDataTool alloc] init];  
  18.       
  19.         NSLog(@"%@ %@ %@ %@", tool1, tool2, tool3, tool4);  
  20. }  
  21.   
  22.   
  23.   
  24. @end  

打印结果

 

 

[objc]   
 
  1. 使用GCD实现单利模式[2334:607] <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0>  

3.非ARC实现单例模式

3.1非ARC内存管理模式下对象必须手动释放,为了防止那个唯一的单例对象被释放掉,则只需要重写下面的几个方法即可

[objc]   
 
  1. - (oneway void)release { }  
  2. - (id)retain { return self; }  
  3. - (NSUInteger)retainCount { return 1;}  
  4. - (id)autorelease { return self;}  

3.2通过新建一个HMDataTool类来演示非ARC单例模式

 
[objc]   
 
  1. //  HMDataTool.h  
  2.   
  3.   
  4. #import <Foundation/Foundation.h>  
  5.   
  6. @interface HMDataTool : NSObject  
  7. + (instancetype)sharedDataTool;  
  8. @end  
[objc]   
 
  1. //  
  2. //  HMDataTool.m  
  3. //  03-单例模式-Singleton(掌握)  
  4. //  
  5. //  Created by apple on 14-9-16.  
  6. //  Copyright (c) 2014年 heima. All rights reserved.  
  7. //  
  8.   
  9. #import "HMDataTool.h"  
  10.   
  11. @implementation HMDataTool  
  12. // 用来保存唯一的单例对象  
  13. static id _instace;  
  14.   
  15. + (id)allocWithZone:(struct _NSZone *)zone  
  16. {  
  17.     static dispatch_once_t onceToken;  
  18.     dispatch_once(&onceToken, ^{  
  19.         _instace = [super allocWithZone:zone];  
  20.     });  
  21.     return _instace;  
  22. }  
  23.   
  24. + (instancetype)sharedDataTool  
  25. {  
  26.     static dispatch_once_t onceToken;  
  27.     dispatch_once(&onceToken, ^{  
  28.         _instace = [[self alloc] init];  
  29.     });  
  30.     return _instace;  
  31. }  
  32.   
  33. - (id)copyWithZone:(NSZone *)zone  
  34. {  
  35.     return _instace;  
  36. }  
  37. /** 
  38.  *  重写下面几个关于引用计数器的方法就可以防止修改引用计数器的值, 
  39.     这样就可以这个对象永远停留在内存中(因为这几个方法都是空的,所以尽管怎么调用,都没有作用) 
  40.  * 
  41.  *  @return <#return value description#> 
  42.  */  
  43.   
  44. - (oneway void)release { }  
  45. - (id)retain { return self; }  
  46. - (NSUInteger)retainCount { return 1;}  
  47. - (id)autorelease { return self;}  
  48.   
  49. @end  
[objc]   
 
  1. //  
  2. //  HMViewController.h  
  3.   
  4.   
  5. #import <UIKit/UIKit.h>  
  6.   
  7. @interface HMViewController : UIViewController  
  8.   
  9. @end  
[objc]   
 
  1. //  
  2. //  HMViewController.m  
  3.   
  4.   
  5.   
  6. #import "HMViewController.h"  
  7. #import "HMDataTool.h"  
  8.   
  9. @interface HMViewController ()  
  10.   
  11. @end  
  12.   
  13. @implementation HMViewController  
  14.   
  15. - (void)viewDidLoad  
  16. {  
  17.     [super viewDidLoad];  
  18.       
  19.     HMDataTool *tool1 = [[HMDataTool alloc] init];  
  20.     HMDataTool *tool2 = [[HMDataTool alloc] init];  
  21.     HMDataTool *tool3 = [HMDataTool sharedDataTool];  
  22.     HMDataTool *tool4 = [HMDataTool sharedDataTool];  
  23.     /** 
  24.      *  重写了下面几个方法之后,则随便释放N次都没有用了 
  25.      - (oneway void)release { } 
  26.      - (id)retain { return self; } 
  27.      - (NSUInteger)retainCount { return 1;} 
  28.      - (id)autorelease { return self;} 
  29.       
  30.      */  
  31.       [tool4 autorelease];  
  32.       [tool4 autorelease];  
  33.       [tool4 autorelease];  
  34.       [tool4 autorelease];  
  35.       [tool4 autorelease];  
  36.       
  37.     NSLog(@"%@ %@ %@ %@", tool1, tool2, tool3, tool4);  
  38. }<pre name="code" class="objc">+(loginModel *)sharedloginModel  
  39. {  
  40.     static loginModel *loginmodle = nil;  
  41.     @synchronized(self)  
  42.     {  
  43.         if (loginmodle == nil) {  
  44.             loginmodle = [[loginModel alloc] init];  
  45.         }  
  46.     }  
  47.       
  48.     return loginmodle;  
  49.       
  50. }  
@end
 运行结果 

单例模式-ARC(掌握)[2592:607] <HMDataTool: 0x8d12600> <HMDataTool: 0x8d12600> <HMDataTool: 0x8d12600> <HMDataTool: 0x8d12600>

 

4.线程锁和GCD实现单例模式

4.1线程锁和GCD实现单粒模式

线程锁实现单粒
[objc]   
 
  1. +(Muser *)sharedMuser  
  2. {  
  3.     staticstatic *user = nil;  
  4.     @synchronized(self)  
  5.     {  
  6.         if (user == nil) {  
  7.             user = [[Muser alloc] init];  
  8.         }  
  9.     }  
  10.       
  11.     return user;  
  12.       
  13. }  
GCD实现单粒
[objc]   
 
  1. +(<span style="font-family: Arial, Helvetica, sans-serif;">sharedsegMentTitles</span><span style="font-family: Arial, Helvetica, sans-serif;"> *</span><span style="font-family: Arial, Helvetica, sans-serif;">)sharedsegMentTitles</span>  
  2. {  
  3.     static SwitchMenuViewModel * segTitles = nil;  
  4.     static dispatch_once_t once;  
  5.     dispatch_once(&once,^{  
  6.    if (segTitles == nil) {  
  7.       segTitles = [[SwitchMenuViewModel alloc]init];  
  8.         }  
  9.     });  
  10.     return segTitles;  
  11. }  

4.2为什么使用宏?

 
假设一个项目中有多个类需要单例,则需要每个类都实现一遍单例,这样很繁琐,因此可以采用定义宏的方式,写一个单例文件添加到项目中然后在项目的Prefix.pch文件中得这个地方包含进去即可
[objc]   
 
  1. // .h文件 shared##name 是让前面HMSingletonH(name) 接收到的参数拼接起来  
  2. #define HMSingletonH(name) + (instancetype)shared##name;  
  3.   
  4. // .m文件  如果是ARC  
  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. //如果是非ARC  
  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  
[objc]   
 
  1. //  
  2. //  HMViewController.m  
  3. //    
  4. #import "HMViewController.h"  
  5. #import "HMMusicTool.h"  
  6. #import "HMMovieTool.h"  
  7. #import "HMDataTool.h"  
  8.   
  9. #import "HMPerson.h"  
  10.   
  11. @interface HMViewController ()  
  12.   
  13. @end  
  14.   
  15. @implementation HMViewController  
  16.   
  17. - (void)viewDidLoad  
  18. {  
  19.     [super viewDidLoad];  
  20.       
  21. //    HMMusicTool *tool1 = [HMMusicTool sharedMusicTool];  
  22. //    HMMusicTool *tool2 = [HMMusicTool sharedMusicTool];  
  23. //  
  24. //    HMMovieTool *tool3 = [HMMovieTool sharedMovieTool];  
  25. //    HMMovieTool *tool4 = [HMMovieTool sharedMovieTool];  
  26. //      
  27. //    HMDataTool *tool5 = [HMDataTool sharedDataTool];  
  28. //    HMDataTool *tool6 = [HMDataTool sharedDataTool];  
  29. //  
  30. //    NSLog(@"%@ %@", tool5, tool6);  
  31.       
  32.     HMPerson *p = [[HMPerson alloc] init];  
  33.       
  34. #if __has_feature(objc_arc)  
  35.     // 编译器是ARC环境  
  36. #else  
  37.     // 编译器是MRC环境  
  38.     [p release];  
  39. #endif  
  40. }  
  41.   
  42. @end  
 
为什么使用宏?
这样可以方便项目中的其它单例的创建,只需要在项目中包含即可共用,而不必要再次用代码为每一个单例对象实现单例
你可能感兴趣的文章
python - 抓取汇率数据分析美元和欧元对RMB的变化曲线
查看>>
python 数据科学 - 【回归分析】 ☞ 线性回归(2)
查看>>
设计模式——工厂模式
查看>>
Unity中实现有限状态机FSM
查看>>
Unity中实现反弹
查看>>
U3D游戏开发框架(九)——事件序列
查看>>
Unity中解决“SetDestination“ can only be called on an active agent that has been placed on a NavMesh
查看>>
Unity中的刚体
查看>>
Unity中的坐标转换
查看>>
Unity中为什么不能对transform.position.x直接赋值?
查看>>
Lua(四)——变量
查看>>
Lua(十四)——元表
查看>>
Lua(十五)——协同程序
查看>>
Lua(十七)——面向对象
查看>>
Lua(十八)——错误处理,垃圾回收
查看>>
xLua(一)——介绍
查看>>
xLua(二)——下载
查看>>
Unity中使用ViedoPlayer操作视频文件
查看>>
Java MyBatis(2)--- generatorConfig.xml详解与运行
查看>>
VueJS(5)---初步练习(5题)
查看>>