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

1.单利模式概述

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

2.使用GCD实现单利模式

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

[objc] view plain copy

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

[objc] view plain copy

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

[objc] view plain copy

  1. #import "htingViewController.h"
  2. #import"HMDataTool.h"
  3. @interface htingViewController ()
  4. @end
  5. @implementation htingViewController
  6. - (void)viewDidLoad
  7. {
  8. [super viewDidLoad];
  9. // Do any additional setup after loading the view, typically from a nib.
  10. HMDataTool *tool1 = [HMDataTool sharedDataTool];
  11. HMDataTool *tool2 = [HMDataTool sharedDataTool];
  12. HMDataTool *tool3 = [[HMDataTool alloc] init];
  13. HMDataTool *tool4 = [[HMDataTool alloc] init];
  14. NSLog(@"%@ %@ %@ %@", tool1, tool2, tool3, tool4);
  15. }
  16. @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. #import <Foundation/Foundation.h>
  3. @interface HMDataTool : NSObject
  4. + (instancetype)sharedDataTool;
  5. @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. #import "HMDataTool.h"
  9. @implementation HMDataTool
  10. // 用来保存唯一的单例对象
  11. static id _instace;
  12. + (id)allocWithZone:(struct _NSZone *)zone
  13. {
  14. static dispatch_once_t onceToken;
  15. dispatch_once(&onceToken, ^{
  16. _instace = [super allocWithZone:zone];
  17. });
  18. return _instace;
  19. }
  20. + (instancetype)sharedDataTool
  21. {
  22. static dispatch_once_t onceToken;
  23. dispatch_once(&onceToken, ^{
  24. _instace = [[self alloc] init];
  25. });
  26. return _instace;
  27. }
  28. - (id)copyWithZone:(NSZone *)zone
  29. {
  30. return _instace;
  31. }
  32. /**
  33. *  重写下面几个关于引用计数器的方法就可以防止修改引用计数器的值,
  34. 这样就可以这个对象永远停留在内存中(因为这几个方法都是空的,所以尽管怎么调用,都没有作用)
  35. *
  36. *  @return <#return value description#>
  37. */
  38. - (oneway void)release { }
  39. - (id)retain { return self; }
  40. - (NSUInteger)retainCount { return 1;}
  41. - (id)autorelease { return self;}
  42. @end

[objc] view plain copy

  1. //
  2. //  HMViewController.h
  3. #import <UIKit/UIKit.h>
  4. @interface HMViewController : UIViewController
  5. @end

[objc] view plain copy

  1. //
  2. //  HMViewController.m
  3. #import "HMViewController.h"
  4. #import "HMDataTool.h"
  5. @interface HMViewController ()
  6. @end
  7. @implementation HMViewController
  8. - (void)viewDidLoad
  9. {
  10. [super viewDidLoad];
  11. HMDataTool *tool1 = [[HMDataTool alloc] init];
  12. HMDataTool *tool2 = [[HMDataTool alloc] init];
  13. HMDataTool *tool3 = [HMDataTool sharedDataTool];
  14. HMDataTool *tool4 = [HMDataTool sharedDataTool];
  15. /**
  16. *  重写了下面几个方法之后,则随便释放N次都没有用了
  17. - (oneway void)release { }
  18. - (id)retain { return self; }
  19. - (NSUInteger)retainCount { return 1;}
  20. - (id)autorelease { return self;}
  21. */
  22. [tool4 autorelease];
  23. [tool4 autorelease];
  24. [tool4 autorelease];
  25. [tool4 autorelease];
  26. [tool4 autorelease];
  27. NSLog(@"%@ %@ %@ %@", tool1, tool2, tool3, tool4);
  28. }<pre name="code" class="objc">+(loginModel *)sharedloginModel
  29. {
  30. static loginModel *loginmodle = nil;
  31. @synchronized(self)
  32. {
  33. if (loginmodle == nil) {
  34. loginmodle = [[loginModel alloc] init];
  35. }
  36. }
  37. return loginmodle;
  38. }

@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. return user;
  11. }

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. // .m文件  如果是ARC
  4. #if __has_feature(objc_arc)
  5. #define HMSingletonM(name) \
  6. static id _instace; \
  7. \
  8. + (id)allocWithZone:(struct _NSZone *)zone \
  9. { \
  10. static dispatch_once_t onceToken; \
  11. dispatch_once(&onceToken, ^{ \
  12. _instace = [super allocWithZone:zone]; \
  13. }); \
  14. return _instace; \
  15. } \
  16. \
  17. + (instancetype)shared##name \
  18. { \
  19. static dispatch_once_t onceToken; \
  20. dispatch_once(&onceToken, ^{ \
  21. _instace = [[self alloc] init]; \
  22. }); \
  23. return _instace; \
  24. } \
  25. \
  26. - (id)copyWithZone:(NSZone *)zone \
  27. { \
  28. return _instace; \
  29. }
  30. //如果是非ARC
  31. #else
  32. #define HMSingletonM(name) \
  33. static id _instace; \
  34. \
  35. + (id)allocWithZone:(struct _NSZone *)zone \
  36. { \
  37. static dispatch_once_t onceToken; \
  38. dispatch_once(&onceToken, ^{ \
  39. _instace = [super allocWithZone:zone]; \
  40. }); \
  41. return _instace; \
  42. } \
  43. \
  44. + (instancetype)shared##name \
  45. { \
  46. static dispatch_once_t onceToken; \
  47. dispatch_once(&onceToken, ^{ \
  48. _instace = [[self alloc] init]; \
  49. }); \
  50. return _instace; \
  51. } \
  52. \
  53. - (id)copyWithZone:(NSZone *)zone \
  54. { \
  55. return _instace; \
  56. } \
  57. \
  58. - (oneway void)release { } \
  59. - (id)retain { return self; } \
  60. - (NSUInteger)retainCount { return 1;} \
  61. - (id)autorelease { return self;}
  62. #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. #import "HMPerson.h"
  9. @interface HMViewController ()
  10. @end
  11. @implementation HMViewController
  12. - (void)viewDidLoad
  13. {
  14. [super viewDidLoad];
  15. //    HMMusicTool *tool1 = [HMMusicTool sharedMusicTool];
  16. //    HMMusicTool *tool2 = [HMMusicTool sharedMusicTool];
  17. //
  18. //    HMMovieTool *tool3 = [HMMovieTool sharedMovieTool];
  19. //    HMMovieTool *tool4 = [HMMovieTool sharedMovieTool];
  20. //
  21. //    HMDataTool *tool5 = [HMDataTool sharedDataTool];
  22. //    HMDataTool *tool6 = [HMDataTool sharedDataTool];
  23. //
  24. //    NSLog(@"%@ %@", tool5, tool6);
  25. HMPerson *p = [[HMPerson alloc] init];
  26. #if __has_feature(objc_arc)
  27. // 编译器是ARC环境
  28. #else
  29. // 编译器是MRC环境
  30. [p release];
  31. #endif
  32. }
  33. @end

为什么使用宏?

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

时间: 2024-12-30 04:01:38

单例模式——使用GCD实现单例模式 & 非ARC单例模式 &使用GCD和线程锁实现单例模式-b的相关文章

iOS学习总结之ARC和非ARC的单例模式实现

iOS单例模式的实现 首先我们要明白下面三个问题: 什么是单例模式 单例模式的优点 如何实现单例模式 1.什么是单例模式 单例模式(Singleton):单例模式确保对于一个给定的类只有一个实例存在,这个实例有一个全局唯一的访问点. 2.单例模式的优点 节省内存开销:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例. 如果有一些数据,整个程序都用得上,使用同一份资源即可.(保证大家访问的数据是相同的,一致的) 例如:[NSUserD

单例模式ARC和非ARC

ARC环境下的单例模式: static id _instance = nil; + (id)allocWithZone:(struct _NSZone *)zone { if (_instance == nil) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); } return _instance; } - (id)init {

java——多线程——单例模式的static方法和非static方法是否是线程安全的?

单例模式的static方法和非static方法是否是线程安全的? 答案是:单例模式的static方法和非static方法是否是线程安全的,与单例模式无关.也就说,如果static方法或者非static方法不是线程安全的,那么不会因为这个类使用了单例模式,而变的安全. 闲话休说,看代码: import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestSingl

高并发下线程安全的单例模式

复制来自 http://blog.csdn.net/cselmu9/article/details/51366946 在所有的设计模式中,单例模式是我们在项目开发中最为常见的设计模式之一,而单例模式有很多种实现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单例的呢?这些问题在看了本文之后都会一一的告诉你答案,赶快来阅读吧! 什么是单例模式? 在文章开始之前我们还是有必要介绍一下什么是单例模式.单例模式是为确保一个类只有一个实例,并为整个

线程安全的单例模式的几种实现

单例模式是一种常见的设计模式:Java Singleton 模式就为我们提供了这样实现的可能.使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数, 有利于Java垃圾回收(garbage collection). 单例模式也是一种比较常见的设计模式,它到底能带给我们什么好处呢?其实无非是三个方面的作用: 1.控制资源的使用,通过线程同步来控制资源的并发访问: 2.控制实例产生的数量,达到节约资源的目的. 3.作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让

ndroid网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合

上文简 单介绍了HttpClient和Tomcat服务器的交互,主角是HttpClient,然后它跟服务器交互有两种方式即get和post.所以这个 HttpClient就类似于电脑上用的浏览器.当我打开多个网页的时候,并不需要开一个网页就开一个浏览器,而是一个浏览器上面开了好几个网页.对应于 HttpClient,即无需连接一次就new一个HttpClient.一般,我们希望一个应用里就一个HttpClient就ok了,就像我们的手机 或PC,没人会呼呼的装好几个浏览器.本文即解决此问题,代码

线程相关的单例模式(C\C++)

最近开发有这样的需求, 我需要一个静态类,我可以在线程中的任何地方调用它的public函数已完成对应的功能: 这个静态类会调用我初始化给它的一个指针,这个指针是与线程一一对应的: 准确来说这种模式应该叫多例模式,它是单例模式和工厂模式的一个变式.下面说一下,我的实现思路. (一)实例指针 如果是单例模式,会有一个指针或者静态变量来存储这个静态变量,而这里多例,则需要使用一个Map来存储,Map的key是当前线程的句柄,Map定义如下: typedef map<DWORD, CRelatedThr

Android之线程安全的单例模式,Adapter注意事项之引用传值

线程安全的单例模式单位模式一般写法如下: public static FestivalLab mInstance; private FestivalLab() { } public static FestivalLab getInstance() { if (mInstance == null) { mInstance = new FestivalLab(); } return mInstance; } 这样写不是线程安全的,因为如果两个线程都进入到这里,会实例化两次.那么如何优化呢? 线程安全

Android网络(4):HttpClient必经之路----使用线程安全的单例模式HttpClient,及HttpClient和Application的融合

上文简单介绍了HttpClient和Tomcat服务器的交互,主角是HttpClient,然后它跟服务器交互有两种方式即get和post.所以这个HttpClient就类似于电脑上用的浏览器.当我打开多个网页的时候,并不需要开一个网页就开一个浏览器,而是一个浏览器上面开了好几个网页.对应于HttpClient,即无需连接一次就new一个HttpClient.一般,我们希望一个应用里就一个HttpClient就ok了,就像我们的手机或PC,没人会呼呼的装好几个浏览器.本文即解决此问题,代码可以直接