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

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

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

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

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. SilverLight 页面后台方法XX.xaml.cs 创建JS,调用JS ,弹出提示框

    1.Invoke和InvokeSelf [c-sharp] view plaincopy public partial class CreateJSDemo : UserControl { publi ...

  2. Memory Analyzer Blog

    引用:http://memoryanalyzer.blogspot.jp/2008/05/automated-heap-dump-analysis-finding.html Dienstag, 27. ...

  3. 基于Pojo的开发模式(day03)

    上一次的文章讨论到了Spring的设计目标:使得JEE开发更易用. ok,作为一个Java开发人员,应该都知道struts这个框架,不知道是否大家都清楚struts1和struts2的区别. 首先,这 ...

  4. 基于'sessionStorage'与'userData'的类session存储

    Storage.js: 注意:此版本实现的存储在符合Web存储标准(ie8及ie8以上的版本与其他主流浏览器)的情况下与session的周期一致,但在页面不关闭的情况下没有过期时间,ie7及以下版本则 ...

  5. FCKeditor插件开发实例:uploadify多文件上传插件

    FCKeditor是一个专门使用在网页上属于开放源代码的所见即所得文字编辑器.它志于轻量化,不需要太复杂的安装步骤即可使用.它可和PHP.JavaScript.ASP.ASP.NET.ColdFusi ...

  6. jquery 实现 隐藏交替同时记住以前隐藏的样式

    /* * control menu show or hide(expand and collapse) */ var status = []; function menuOperation() { $ ...

  7. CSU 1335 高桥和低桥

    开始队友说是线段树,看了看貌似也是,上手敲了个嵌套的线段树,O(nlognlogn)的复杂度果断tle了 TAT 思路:对h[i]排序,对每次涨水退水,先用二分查找,再用一个数组保存当前点之后所有点被 ...

  8. bzoj 3238 Ahoi2013 差异

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2357  Solved: 1067[Submit][Status ...

  9. GetProcessMemoryInfo API取得进程所用的内存

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms683219(v=vs.85).aspx 例子: https://msdn.mic ...

  10. The Most Wanted Letter

    The Most Wanted Letter You are given a text, which contains different english letters and punctuatio ...