iOS开发-单例模式的解读
现在网上的有很多人写单例模式,一个很基本的东西但是版本也有很多,新人看了难免有些眼花缭乱的感觉。自己最新比较闲,也过来写一些自己的心得。
在往下看之前,我们要明白一点,那就是在什么情况下我们才要用到单例模式呢?单例模式在一般情况下用于当一个类只能有一个实例的时候,或者说当一个类只需要定义一个,而且还要被重复使用的时候将它定义成为单例是最好的。(例如视频播放器,音频播放器等工具类用用单例模式加以控制是非常合适的)
在创建一个单例之前,我们还需要知道一点,那就是我们创建一个单例,我们的最终目的是什么呢?
单例模式需要达到的目的:
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开发-单例模式的解读的更多相关文章
- iOS开发--单例模式
单例模式在iOS开发中可能算是最常用的模式之一了,但是由于oc本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦,这里我就抛砖引玉来聊一聊iOS中单例模式的设计思路.关于单例模式更多的介绍请参考 ...
- iOS开发单例模式 dispatch_once
什么是单例 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源 ...
- iOS开发——单例模式
一.用if语句实现单例 1.在.h文件中 #import <Foundation/Foundation.h> @interface YYTRequestTool : NSObject +( ...
- ios 开发之单例模式
在iOS开发中,有很多地方都选择使用单例模式.有很多时候必须要创建一个对象,并且不能创建多个,用单例就为了防止创建多个对象.单例模式的意思就是某一个类有且只有一个实例.单例模式确保某一个类只有一个实例 ...
- iOS开发多线程篇—单例模式(ARC)
iOS开发多线程篇—单例模式(ARC) 一.简单说明: 设计模式:多年软件开发,总结出来的一套经验.方法和工具 java中有23种设计模式,在ios中最常用的是单例模式和代理模式. 二.单例模式说明 ...
- iOS开发——实用技术OC篇&单例模式的实实现(ACR&MRC)
单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...
- iOS开发笔记-两种单例模式的写法
iOS开发笔记-两种单例模式的写法 单例模式是开发中最常用的写法之一,iOS的单例模式有两种官方写法,如下: 不使用GCD #import "ServiceManager.h" ...
- IOS开发中单例模式使用详解
第一.基本概念 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问. 第二.在IOS中使用单例模式的情 ...
- iOS开发CoreAnimation解读之三——几种常用Layer的使用解析
iOS开发CoreAnimation解读之三——几种常用Layer的使用解析 一.CAEmitterLayer 二.CAGradientLayer 三.CAReplicatorLayer 四.CASh ...
随机推荐
- 正则表达式,Regex类
C#regex是正则表达式类用于string的处理,查找匹配的字符串.1,先看一个例子Regex regex=new Regex(@”OK“)://我们要在目标字符串中找到"OK" ...
- Bootstrap新手常见问题
题记 bootstrap这个开源的UI库确实很方便,用了两日,觉得不错,但也有些问题比较头疼! 主题 1.怎么使用?怎么定制?下面是一个范例,修改了navbar的颜色,重新设置了select控件的默认 ...
- 移动web开发中遇到的一些问题收纳
1.获取滚动条的值: window.scrollY window.scrollX 桌面浏览器中想要获取滚动条的值是通过document.scrollTop和document.scrollLeft得到的 ...
- iOS学习之界面间传值
/** * 界面间传值步骤 1.界面传值第一种场场景:从前往后传值. 秘诀:属性传值.(葵花宝典). 招式:(1).在后一个界面定义属性,属性的类型和传出数据类型一致. (2).在进入下一界面之前, ...
- Silverlight js html 相互调用
1.sl调用js 比如我们在页面中定义一个js函数: <script type="text/javascript"> function fnTest(ms ...
- Java学习笔记--AWT事件处理
1.事件模型 在整个事件触发和相应的过程中,主要涉及一下3类对象 (1) 事件源 : 引起时间的GUI对象,如各类组件(Button,Label,TextField),容器组件(Frame,panel ...
- Windows PowerShell是啥?看完本文你就懂它了
这篇文章主要介绍了Windows PowerShell是啥?Windows PowerShell是什么?Windows PowerShell有哪些特性?Windows PowerShell有什么用?看 ...
- 使用jQuery来检测远程图片文件是否存在
使用jQuery来检测远程图片文件是否存在 最近为我的憨豆人笑园添加图片功能时,遇到了这个问题,用户可以填写一个远程的图片地址,也可以上传一个本地图片.为了不浪费服务器的资源,我们需要在客户端先对用户 ...
- seajs教程之seajs学习笔记 seajs.use用法
seajs.use 用来在页面中加载模块.通过 use 方法,可以在页面中加载任意模块. 实例地址:http://www.android100.org/html/201405/23/12807.htm ...
- RedHat9通过Host-only配置网络连接
首先我用的是VMware8版本安装的RedHat9.VMware给我们提供了三种让虚拟机里的安装系统连上网的方式.分别是Host-only,Bridge,NAT.我要讲的是Host-only. 第一步 ...