A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

单例模式
单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
1.单例模式的要点:
  显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
2.单例模式的优点:
  1.实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例。
  2.灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

IOS中的单例模式
  在objective-c中要实现一个单例类,至少需要做以下四个步骤:
  1、为单例对象实现一个静态实例,并初始化,然后设置成nil,
  2、实现一个实例构造方法检查上面声明的静态实例是否为nil,如果是则新建并返回一个本类的实例,
  3、重写allocWithZone方法,用来保证其他人直接使用alloc和init试图获得一个新实力的时候不产生一个新实例,
  4、适当实现allocWitheZone,copyWithZone,release和autorelease。

单例模式的创建

本文以创建一个MySingletonClass的单例模式为例。首先,我们需要定义一个类MySingletonClass.

  1. @interface MySingletonClass:NSObject {  
  2.       
  3. }
复制代码

并且为其添加一个类方法(注意,这里不是实例方法)+(id)sharedInstance;一个基本的实现写法如下:

  1. static MySingletonClass *sharedCLDelegate = nil;  
  2. +(MySingletonClass *)sharedInstance{  
  3.     @synchronized(self) {  
  4.         if(sharedCLDelegate == nil) {  
  5.             [[[self class] alloc] init]; //   assignment   not   done   here  
  6.         }  
  7.     }  
  8.     return sharedCLDelegate;  
  9. }  
复制代码

在上面的代码中(用到了关键字@synchronized是为了保证我们的单例的线程级别的安全,可以适用于多线程模式下。)static变量sharedCLDelegate用于存储一个单例的指针,并且强制所有对该变量的访问都必须通过类方法   +(id)sharedInstance,在对   +(id)sharedInstance第一次调用时候完成实例的创建。这里值得留意一下的是,上面代码中用的是[[selfclass] alloc],而不是 [MySingletonClass alloc],一般情况下这两种写法产生同样的效果,但是这里这样做是为了更好的利用OOP的性质,[selfclass]可以动态查找并确定类的类型从而便于实现对该类的子类化。


对实例化的控制

为了完全的实现实例的单态性,必须通过一定手段来避免实例多次被创建。+(id)sharedInstance控制了单例的创建和访问,但是并不能控制其它地方的代码通过alloc方法来创建更多的实例,因此我们还要重载任何一个涉及到allocation的方法,这些方法包括   +new, +alloc,+allocWithZone:, -copyWithZone:, 以及 -mutableCopyWithZone: 另外,+(id)sharedInstance也需要稍作修改。

  1. + (id)hiddenAlloc  
  2. {  
  3.     return [super alloc];  
  4. }  
  5.   
  6.   
  7. + (id)alloc  
  8. {  
  9.     NSLog(@"%@: use +sharedInstance instead of +alloc", [[self class] name]);  
  10.     return nil;  
  11. }  
  12.   
  13.   
  14. + (id)new  
  15. {  
  16.     return [self alloc];  
  17. }  
  18.   
  19. +(id)allocWithZone:(NSZone*)zone  
  20. {  
  21.     return [self alloc];  
  22. }  
  23.   
  24. -   (id)copyWithZone:(NSZone *)zone  
  25. {   // -copy inherited from NSObject calls -copyWithZone:  
  26.     NSLog(@"MySingletonClass: attempt to -copy may be a bug.");  
  27.     [self retain];  
  28.     return self;  
  29. }  
  30.   
  31. - (id)mutableCopyWithZone:(NSZone *)zone  
  32. {  
  33.     // -mutableCopy inherited from NSObject calls -mutableCopyWithZone:  
  34.     return [self copyWithZone:zone];  
  35. }  
  36.   
  37. +(id)sharedInstance修改如下:  
  38.   
  39. + (MySingletonClass *)sharedInstance {  
  40.     @synchronized(self) {  
  41.         if (sharedCLDelegate == nil)   {  
  42.             [[[self class] hiddenAlloc] init]; // assignment not done here  
  43.         }  
  44.     }  
  45.     return sharedCLDelegate;  
  46. }
复制代码

如果不考虑类的子类化,+hiddenAlloc这个方法可以省略。由于我们是用[selfclass]来实现类型的动态识别,用[[selfclass] hiddenAlloc]可以避免调用到被重载过的alloc方法。此外,hiddenAlloc也为可能的子类化提供了一个调用原始alloc方法的机会。上面重载过的alloc方法只是给出一个log信息并且返回nil。Copying方法里只是简单的增加了retain的计数并没有返回一个新的实例。这也正体现了单例模式的性质,因为技术上来讲,拷贝一个单例是错误的(因为是“单例”)所以在copyWithZone方法中我们给出了一个错误信息,当然也可以扔出一个exception。


单例的销毁

通常我们在   -(void)applicationWillTerminate:(UIApplication *)application方法中调用如下方法:


  1. + (void)attemptDealloc  
  2. {  
  3.     if ([sharedCLDelegate retainCount] != 1)  
  4.         return;  
  5.   
  6.     [sharedCLDelegate release];  
  7.     myInstance = nil;  
  8. }  
复制代码



评分

参与人数 1技术分 +1 收起 理由
傘が咲く + 1

查看全部评分

9 个回复

倒序浏览
学习了 我也快进入考试了
回复 使用道具 举报
我也碰到这道题了
回复 使用道具 举报

版主顶着不给分么
回复 使用道具 举报
学习了学习了
回复 使用道具 举报
视频中一直找不到单例,正发愁这个东西呢?
另外弱弱问下,试题不是不让百度么?
回复 使用道具 举报
学习了  
回复 使用道具 举报
baby14 金牌黑马 2018-9-16 11:56:46
8#
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马