1.单利模式概述

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

2.使用GCD实现单利模式

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

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

打印结果

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

3.非ARC实现单例模式

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

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

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

 
  1. //  HMDataTool.h
  2. #import <Foundation/Foundation.h>
  3. @interface HMDataTool : NSObject
  4. + (instancetype)sharedDataTool;
  5. @end
  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
  1. //
  2. //  HMViewController.h
  3. #import <UIKit/UIKit.h>
  4. @interface HMViewController : UIViewController
  5. @end
  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实现单粒模式

线程锁实现单粒
  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实现单粒

  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文件中得这个地方包含进去即可
  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
  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

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

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

  1. 单例模式ARC和非ARC

    ARC环境下的单例模式: static id _instance = nil; + (id)allocWithZone:(struct _NSZone *)zone { if (_instance = ...

  2. Objective-C在ARC下结合GCD的单例模式和宏模版

    单例模式在iOS开发过程中经常用到,苹果提供过objective c单例的比较官方的写法: static MyGizmoClass *sharedGizmoManager = nil; + (MyGi ...

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

    iOS单例模式的实现 首先我们要明白下面三个问题: 什么是单例模式 单例模式的优点 如何实现单例模式 1.什么是单例模式 单例模式(Singleton):单例模式确保对于一个给定的类只有一个实例存在, ...

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

    单例模式的static方法和非static方法是否是线程安全的? 答案是:单例模式的static方法和非static方法是否是线程安全的,与单例模式无关.也就说,如果static方法或者非static ...

  5. java多线程(一)——线程安全的单例模式

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3. ...

  6. [No000016F]高并发下线程安全的单例模式(最全最经典)

    在所有的设计模式中,单例模式是我们在项目开发中最为常见的设计模式之一,而单例模式有很多种实现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单 ...

  7. 【多线程那些事儿】如何使用C++写一个线程安全的单例模式?

    如何写一个线程安全的单例模式? 单例模式的简单实现 单例模式大概是流传最为广泛的设计模式之一了.一份简单的实现代码大概是下面这个样子的: class singleton { public: stati ...

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

    线程安全的单例模式单位模式一般写法如下: public static FestivalLab mInstance; private FestivalLab() { } public static Fe ...

  9. 线程安全的单例模式还需要对成员变量的set get方法设置锁么

    不需要,线程安全的单例模式,在获得对象时已经加锁了,保证每时每刻只有一个线程获得此单例对象.所以不需要再上锁了啊

随机推荐

  1. bzoj3675: [Apio2014]序列分割

    留坑 为什么别人家的斜率优化跟我一点都不一样! 为什么斜率都要变成正的... 为什么要那么推式子 为什么不能直接做啊..... 为什么不把0去掉去秒WA啊 为什么叉积去了0也过不了啊 woc啊 #in ...

  2. java基础之 IO流

    javaIO流   IO流 : (input  output) 输入输出流 :输入 :将文件读到内存中 输出:将文件从内存输出到其他地方.   IO技术的作用:主要就是解决设备和设备之间的数据传输问题 ...

  3. JAVA Web学习篇--Servlet

    Servlet由来 做过BS项目的人都知道,浏览器可以依据HTML静态标记语言来显示各式各样的网页.可是假设我们须要在网页上完毕一些业务逻辑:比方登陆验证.或者说网页显示的内容在server的数据库中 ...

  4. 关于Win8对getElementsByTagName等dom方法兼容性的替代方法

    在对Twebbrowser进行dom编程时,引用MSHTML并使用其中的HTMLDocument; IHTMLElementCollection;IHTMLElement;能获得较好的代码提示 其中封 ...

  5. Android 自定义Spinner和其下拉窗口

    : 自定义Spinner其实包括两个部分: 第一部分是用来打开下拉列表的按钮,如图,这个绿色背景直接设置Spinner的背景就行,素材文件如下: 里面的文字需要注意下,Spinner控件没有直接修改文 ...

  6. sql语句实现随机取n条数据(转)

    我想把数组打乱随机取些值,于是用PHP的shuffl()打乱数组,当然,array_rand()也是可以随机取数组的,但是我想到另一个更高效的办法,是不是能用sql直接随机数据?当然可以! mysql ...

  7. 聊一聊Android 6.0的运行时权限

    Android 6.0,代号棉花糖,自发布伊始,其主要的特征运行时权限就很受关注.因为这一特征不仅改善了用户对于应用的使用体验,还使得应用开发者在实践开发中需要做出改变. 没有深入了解运行时权限的开发 ...

  8. MySQL(10):实体、实体表和外键(foreign key)

    1.实体        数据库管理系统中的各种用于数据管理方便而设定的各种数据管理对象,如:数据库表.视图.存储过程等都是数据库实体.广义上讲,这些对象中所存储的数据也是数据库实体.因为它们也是确切存 ...

  9. springmvc配置文件 spring-servlet

    <?xml version="1.0" encoding="UTF-8"?><!-- Bean头部 --><beans xmlns ...

  10. javascript动画效果

    之前工作项目中,运用了缓动动画的效果,在网上看到其他大牛写的相关公式,结合工作需要,进行了整理,拿出来跟大家分享下,js代码中,只运用了一个小功能进行了测试 <!DOCTYPE html> ...