单例模式——使用GCD实现单例模式 & 非ARC单例模式 &使用GCD和线程锁实现单例模式-b

Posted qigemingnan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式——使用GCD实现单例模式 & 非ARC单例模式 &使用GCD和线程锁实现单例模式-b相关的知识,希望对你有一定的参考价值。

1.单利模式概述

 链接:  iOS开发懒汉模式&恶寒模式

2.使用GCD实现单利模式

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

 

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

 

[objc] view plain copy
 技术分享技术分享
  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] view plain copy
 技术分享技术分享
  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] view plain copy
 技术分享技术分享
  1. 使用GCD实现单利模式[2334:607] <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0>  

3.非ARC实现单例模式

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

[objc] view plain copy
 技术分享技术分享
  1. - (oneway void)release { }  
  2. - (id)retain { return self; }  
  3. - (NSUInteger)retainCount { return 1;}  
  4. - (id)autorelease { return self;}  

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

 
[objc] view plain copy
 技术分享技术分享
  1. //  HMDataTool.h  
  2.   
  3.   
  4. #import <Foundation/Foundation.h>  
  5.   
  6. @interface HMDataTool : NSObject  
  7. + (instancetype)sharedDataTool;  
  8. @end  
[objc] view plain copy
 技术分享技术分享
  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] view plain copy
 技术分享技术分享
  1. //  
  2. //  HMViewController.h  
  3.   
  4.   
  5. #import <UIKit/UIKit.h>  
  6.   
  7. @interface HMViewController : UIViewController  
  8.   
  9. @end  

[objc] view plain copy
 技术分享技术分享
  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] view plain copy
 技术分享技术分享
  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] view plain copy
 技术分享技术分享
  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] view plain copy
 技术分享技术分享
  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] view plain copy
 技术分享技术分享
  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  



 
为什么使用宏?
这样可以方便项目中的其它单例的创建,只需要在项目中包含即可共用,而不必要再次用代码为每一个单例对象实现单例

以上是关于单例模式——使用GCD实现单例模式 & 非ARC单例模式 &使用GCD和线程锁实现单例模式-b的主要内容,如果未能解决你的问题,请参考以下文章

设计模式 创建者模式 -- 创建者模式概述 & 单例设计模式的介绍和实现(饿汉式 & 懒汉式)

golang单例模式

golang单例模式

python-单例模式&工厂模式

C++单例模式实现(线程安全&支持多参数构造)

单例模式(补充)