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

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

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

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

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. oc随笔六:字典

    #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { ...

  2. 【android】修改android默认应用图标

    我自己做的一个小程序,想更改程序安装后的默认显示图片,但是我发现只能改一次,以后再改还是显示第一次更改后的图片(此时我已把最后一次更改前的全部图片都删除了,所以不会是名称填错),这是为什么??求高人指 ...

  3. 再谈Redirect(客户端重定向)和Dispatch(服务器端重定向)

    这是两个常常被放在一起进行比较的概念,今天对这两个概念再重新回顾一下,前者发生在客户端(浏览器),后者发生在服务器端,因此也有人把前者称为客户端重定向,把后者称为服务器端重定向,虽然对于后者这种称谓并 ...

  4. (摘) MDI登陆问题

    MDI编程中需要验证用户身份,那么登陆窗口就需要在验证密码后进行相关的隐藏处理. (1)隐藏登陆窗口(登陆窗体作为启动) 登陆按钮事件:this.Hide();//隐藏登陆窗口MDI_Name M = ...

  5. Oracle instr用法

    1:实现indexOf功能,.从第1个字符开始,搜索第1次出现子串的位置 ,) as i from dual; select instr('oracle','or') as i from dual; ...

  6. mysql 命令行 自动补全

    配置文件中 默认关闭自动补全: [mysql] #no-auto-rehash # faster start of mysql but no tab completition 改为: [mysql] ...

  7. zoj 3772 Calculate the Function

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5235 这道题需要构造矩阵:F(X)=F(X-1)+F(X-2)*A(X)转化为 ...

  8. 关于php-fpm通讯时没有REQUEST_METHOD的问题

    nginx是通过fastcgi协议来和php通讯的!而php-fpm就扮演了这样的角色 fastcgi协议 中文版http://blog.chinaunix.net/uid-380521-id-241 ...

  9. Check whether a given Binary Tree is Complete or not 解答

    Question A complete binary tree is a binary tree in which every level, except possibly the last, is ...

  10. spftlayer 安装及简单使用

    1,yum -y install python-pip; pip(Python packet index);