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

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

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

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

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. poj2456 二分逼近寻找正确答案

    Aggressive cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10078   Accepted: 4988 ...

  2. C/C++中的switch使用

    代码: #include <iostream> #include <string> #include <cstdio> using namespace std; i ...

  3. 操作html标签之找到标签(续)

    为了方便我们快速地找到一些特殊的元素,js提供了几个有用的东东. 1.快速找到根元素:document.documentElement和document.body. 2.obj.parentNode: ...

  4. DataTables获取表单输入框数据

    $(document).ready(function() { var table = $('#example').DataTable(); $('button').click(function() { ...

  5. php 和 apache的关系

    例如在客户端游览器输入他也回把这个地址传送到192.168.1.100里的apache里的,apache一看你传过来的是Php文件,如果在服务器没装php的情况下,他也会把这个文件打开,把里面的代码全 ...

  6. Centos下配置Java运行环境

    今天搞了个阿里云,Centos主机 先搞了Tomcat 然后配置Java环境 1.修改文件可执行 chmod 777 (u+x) 文件名 2.配置环境变量 vi /etc/profile 加入如下代码 ...

  7. ByteArrayOutputStream的用法

    ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区,然后利用ByteArrayOutputStream和ByteArrayInputStream的 ...

  8. 实例解析shell子进程(subshell )

    http://blog.csdn.net/sosodream/article/details/5683515 http://blog.csdn.net/firefoxbug/article/detai ...

  9. 《Programming WPF》翻译 第5章 2.内嵌样式

    原文:<Programming WPF>翻译 第5章 2.内嵌样式 每一个“可样式化”的WPF元素都有一个Style属性,可以在内部设置这个属性--使用XAML属性-元素的语法(在第一章讨 ...

  10. 浅谈JS数据类型存储问题

    背景       一个经典的问题,先抛出来给大伙看看: var a = "黑MAO"; var b = a; var c = new Object(); var d = c; a ...