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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

单例模式
单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
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 个回复

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

版主顶着不给分么

点评

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