现在网上的有很多人写单例模式,一个很基本的东西但是版本也有很多,新人看了难免有些眼花缭乱的感觉。自己最新比较闲,也过来写一些自己的心得。

在往下看之前,我们要明白一点,那就是在什么情况下我们才要用到单例模式呢?单例模式在一般情况下用于当一个类只能有一个实例的时候,或者说当一个类只需要定义一个,而且还要被重复使用的时候将它定义成为单例是最好的。(例如视频播放器,音频播放器等工具类用用单例模式加以控制是非常合适的)

在创建一个单例之前,我们还需要知道一点,那就是我们创建一个单例,我们的最终目的是什么呢?

单例模式需要达到的目的:

1. 封装一个共享的资源

2. 提供一个固定的实例创建方法

3. 提供一个标准的实例访问接口

好了,接下来我们就要开始了,为了规范我们应该需要知道创建一个单例具体是有哪几个步骤呢?

在iOS中我们创建一个单例类,我们需要做3个步骤

1、先为我们要做的单例创建一个静态实例,并初始化它,然后设置成为nil;

2、在下面的实例构造方法中检查在第1步中声明的静态实例是否为nil,若判断为真,那么就新建一个并且返回一个本例的实例;

3、重载所有涉及到allocation的方法,对allocWithZone,copyWithZone,release以及autorelease进行重载,这样的话即使在别的地方使用alloc和init方法创建该类的话也不会再产生一个新的实例了;

单例模式的创建

假设以创建一个PlayViewController的单例模式为例:

1、首先创建一个静态实例

1 static PlayViewController *PlayManager = nil;  

2、然后为其添加一个类方法

1 static PlayViewController *PlayManager = nil;  

2+ ( PlayViewController *)defaultManager{  

3     @synchronized(self) {  

4         if(PlayManager == nil) {  

5             [[[self class] alloc] init]; 

6         }  

7     }  

8     return PlayManager;  

9 }  

回顾总结:

a、用到了关键字@synchronized是为了保证我们的单例的线程级别的安全,可以适用于多线程模式下。

b、static变量PlayManager用于存储一个单例的指针,并且强制所有对该变量的访问都必须通过类方法 +(id)defaultManager,在对 +(id)defaultManager第一次调用时候完成实例的创建。

c、上面代码中用的是[[self   class] alloc],而不是 [PlayViewController alloc],一般情况下这两种写法产生同样的效果,但是这里这样做是为了更好的利用OOP的性质,[self class]可以动态查找并确定类的类型从而便于实现对该类的子类化。

3、这个时候创建的单例并不能说是真正意义上的单例,因为他还不具备单例的单态性,所以我们还要通过一些方法来避免单例被多次重复创建。也就是说当用户不使用+(id)defaultManager创建对象,而是使用alloc方法创建对象时,就会又生成一个对象实例,这跟我们最初只想创建一个单例的想法相冲突,那么我们怎么办呢?

我们可以看到,在方法+(PlayViewController *)defaultManager中只是解决了单例的创建和访问,但是并不能限制其他地方的代码通过alloc方法来创建更多的实例,所以,所有涉及到allocation的方法我们都需要进行重载,这些方法包括+(id)alloc、+(id)allocWithZone、-(id)copyWithZone。

1 + (id)alloc  

2 {  

3     @synchronized(self) {  

4         if(PlayManager == nil) {  

5             PlayManager = [super alloc];  

6         }  

7   return PlayManager;  

8        } 

9 }  

1 +(id)allocWithZone:(NSZone*)zone

2 {  

3     @synchronized(self) {  

4         if(PlayManager == nil) {  

5             PlayManager = [super allocWithZone:zone]; 

6             }

7                return  PlayManager;

8         } 

9 }  

1 -   (id)copyWithZone:(NSZone *)zone  

2 {      

3     return self;  

4 }  

回顾总结:

很多时候,我们会发现在有的单例里面对于alloc方法,并没有进行重载,而只是单纯的重载了allocWithZone方法。这是为什么呢?

因为重载allocWithZone是一个比较全面的方法,在使用alloc方法时,alloc方法自身会调用allocWithZone这个方法。而使用allocWithZone时则不会调用alloc方法。

所以很多时候没必要重写alloc,直接重写allocWithZone即可。(也就是说只要定义一个allocWithZone就可以了)

上述的代码只是在ARC中可以正确使用,如果实在MRC中,有retain,copy,release, autorelease,这些方法都会使得引用计数变化,所以,我们都需要对这些方法重写。

1 -   (id)retain

2 {    

3     return self;  

4

1 -   (id)copy

2 {    

3     return self;  

4 }  

1- (oneway void) release

2{

3

4}

1- (id) autorelease

2{

3    return self;

4}

1- (NSUInteger) retainCount

2{

3    return 1;

4}

1- (id)init

2{

3    @synchronized(self) {

4        [super init];//往往放一些要初始化的变量.

5        return self;

6    }

7 }

好了,到这里为止,一个单例的创建算是正式结束了。

谢谢大家的阅读,如果发现有什么不妥当的地方,还请大家留言指出问题!!!

iOS开发-单例模式的解读的更多相关文章

  1. iOS开发--单例模式

    单例模式在iOS开发中可能算是最常用的模式之一了,但是由于oc本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦,这里我就抛砖引玉来聊一聊iOS中单例模式的设计思路.关于单例模式更多的介绍请参考 ...

  2. iOS开发单例模式 dispatch_once

    什么是单例 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源 ...

  3. iOS开发——单例模式

    一.用if语句实现单例 1.在.h文件中 #import <Foundation/Foundation.h> @interface YYTRequestTool : NSObject +( ...

  4. ios 开发之单例模式

    在iOS开发中,有很多地方都选择使用单例模式.有很多时候必须要创建一个对象,并且不能创建多个,用单例就为了防止创建多个对象.单例模式的意思就是某一个类有且只有一个实例.单例模式确保某一个类只有一个实例 ...

  5. iOS开发多线程篇—单例模式(ARC)

    iOS开发多线程篇—单例模式(ARC) 一.简单说明: 设计模式:多年软件开发,总结出来的一套经验.方法和工具 java中有23种设计模式,在ios中最常用的是单例模式和代理模式. 二.单例模式说明 ...

  6. iOS开发——实用技术OC篇&单例模式的实实现(ACR&MRC)

    单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...

  7. iOS开发笔记-两种单例模式的写法

    iOS开发笔记-两种单例模式的写法   单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" ...

  8. IOS开发中单例模式使用详解

    第一.基本概念 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问. 第二.在IOS中使用单例模式的情 ...

  9. iOS开发CoreAnimation解读之三——几种常用Layer的使用解析

    iOS开发CoreAnimation解读之三——几种常用Layer的使用解析 一.CAEmitterLayer 二.CAGradientLayer 三.CAReplicatorLayer 四.CASh ...

随机推荐

  1. C#中Byte转换相关的函数

    1.将一个对象转换为byte对象 public static byte GetByte(object o) { ; if (o != null) { byte tmp; if (byte.TryPar ...

  2. C# 几十万级数据导出Excel,及Excel各种操作

    先上导出代码 /// <summary> /// 导出速度最快 /// </summary> /// <param name="list">&l ...

  3. onsubmit提交前先验证(验证不通过阻止form提交)

    <form  onsubmit = "return val();"> <input type="submit" value="提交& ...

  4. C++新式类型转换

    C++的四种强制类型转换,所以C++不是类型安全的.分别为:static_cast , dynamic_cast , const_cast , reinterpret_cast 新类型的强制转换可以提 ...

  5. 无法捕获的异常:MissingMethodException

    今天一个同事发布站点,一直出现一些稀奇古怪的问题,各种各样的异常都有,根据这些异常去排查代码,都完全正常,很让人郁闷,因为代码里可能出异常的地方都记录了程序日志,所以他一直没去排查系统里的“应用程序日 ...

  6. 【7】用Laravel5.1开发一个简单的博客系统

    声明: 本教程参考Jeffrey way 在laracasts.com上的视频教程,感谢Jeffrey way为大家带来的精彩教程,本教程如有侵权,请及时告知,联系邮箱wanglv93@gmail.c ...

  7. Java Load Properties 文件,定义message信息

    初始化Properties对象,load properties文件: private static final Properties MESSAGERESOURCES = new Properties ...

  8. IOS 文件管理 2

    IOS开发-文件管理(二) 五.Plist文件 String方式添加               NSString *path = [NSHomeDirectory( )  stringByAppen ...

  9. Linux - SSH - Password-less login - generate public key - migrate data without password between two VM servers

    SUMMARY:two server : A , Bsource server : Adestination server : Bthe steps of migrate data from A to ...

  10. [Codeforces Round #186 (Div. 2)] A. Ilya and Bank Account

    A. Ilya and Bank Account time limit per test 2 seconds memory limit per test 256 megabytes input sta ...