OC中两种单例实现方式
OC中两种单例实现方式
写在前面
前两天探索了一下C++ 的单例,领悟深刻了许多。今天来看看OC中的单例又是怎么回事。查看相关资料,发现在OC中一般有两种实现单例的方式,一种方式是跟C++ 中类似的常规实现方法,另一种是利用GCD来实现的。接下来分别看看这两种单例实现方式是怎么做的
常规实现
与C++中的相似,在OC中实现单例需要满足以下条件:
设计一个私有的构造方法
设计一个私有的,本类的对象
设计一个类方法,作为2中类对象的全局访问点
接下来我们逐个解决上述3个条件。
首先,将构造函数设计为私有的。在OC中,对象的创建包括两个步骤:内存申请(alloc)和初始化(init)。也就是说,如果我们希望构造函数私有,那么我们要自己定义alloc方法,使得每次调用该方法,都返回条件2中的对象。在OC中,调用alloc时,alloc实际上是调用allocWithZone这个方法来申请内存的,因此,我们在设计单例的时候,要重写这个方法。另外,我们还要保证使用copy复制单例中的对象时,返回的也是步骤2中的对象,而不会重新创建,因此,我们还要重写copyWithZone这个方法。具体代码如下
.h文件:
//
// Singleton.h
// Singleton
//
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
//类方法
+ (Singleton *) getInstance;
@end
.m文件
//
// Singleton.m
// Singleton
//
#import "Singleton.h"
@implementation Singleton
//在.m文件中声明静态的类实例,不放在.h中是为了让instance私有
static Singleton* instance = nil;
//提供的类唯一实例的全局访问点
//跟C++中思路相似,判断instance是否为空
//如果为空,则创建,如果不是,则返回已经存在的instance
//不能保证线程安全
+(Singleton *) getInstance{
if (instance == nil) {
instance = [[Singleton alloc] init];//调用自己改写的”私有构造函数“
}
return instance;
}
//相当于将构造函数设置为私有,类的实例只能初始化一次
+(id) allocWithZone:(struct _NSZone*)zone
{
if (instance == nil) {
instance = [super allocWithZone:zone];
}
return instance;
}
//重写copy方法中会调用的copyWithZone方法,确保单例实例复制时不会重新创建
-(id) copyWithZone:(struct _NSZone *)zone
{
return instance;
}
@end
main函数文件
// main.m
// Singleton
//
#import <Foundation/Foundation.h>
#import "Singleton.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
//用getInstance方法创建实例1、2并打印内容
Singleton *singleton1 = [Singleton getInstance];
NSLog(@"singleton1 = %@.", singleton1);
Singleton *singleton2 = [Singleton getInstance];
NSLog(@"singleton2 = %@.", singleton2);
//用alloc+init创建实例3并打印内容
Singleton *singleton3 = [[Singleton alloc] init];
NSLog(@"singleton3 = %@.", singleton3);
//用alloc+init创建实例4,打印copy后的内容
Singleton *singleton4 = [[Singleton alloc] init];
NSLog(@"singleton4 = %@.", [singleton4 copy]);
}
return 0;
}
/
结果

可以看到,所有的是咧地址都是相同的,也就是或,返回的是同一个地址
GCD方式的单例
GCD是苹果提供的一种多线程的实现方案。使用GCD,用户不用手动管理线程的生命周期,非常方便。GCD提供了一个多线程下,一段代码只被执行一次的方式:dispath_once。这种方式是线程安全的。代码如下,(其余代码与常规方式相同,不再复制)
//使用gcd中的dispatch_once()方法,函数的第二个参数是一个代码段,告诉gcd我们要做的事情是什么
+(Singleton *) getInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc]init];
});
return instance;
}
//使用gcd的dispatch_once()方法,在传入的代码段中,调用父类的内存申请函数
+(id) allocWithZone:(struct _NSZone*)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
}); return instance;
}
结果如下:

这个结果也证明了,最后创建的类的实例只有一个
OC中两种单例实现方式的更多相关文章
- Hibernate中两种获取Session的方式
转自:https://www.jb51.net/article/130309.htm Session:是应用程序与数据库之间的一个会话,是hibernate运作的中心,持久层操作的基础.对象的生命周期 ...
- hadoop中两种上传文件方式
记录如何将本地文件上传至HDFS中 前提是已经启动了hadoop成功(nodedate都成功启动) ①先切换到HDFS用户 ②创建一个user件夹 bin/hdfs dfs -mkdir /user ...
- Hibernate中两种删除用户的方式
第一种,是比较传统的,先根据主键列进行查询到用户,在进行删除用户 //删除数据 public void deleteStudent(String sno) { init() ; Student qu ...
- Java中两种实现多线程方式的对比分析
本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...
- mybatis中两种取值方式?谈谈Spring框架理解?
1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...
- FMX有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法(firemonkey messaging)
看FMX代码,发现有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法. 早前,看过文章说TMessageManage ...
- 【Java】设计模型-五种单例模型
一. 什么是单例模式 只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计. 单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在. 单例模式有很多好处,它能够 ...
- Java中有两种实现多线程的方式以及两种方式之间的区别
看到一个面试题.问两种实现多线程的方法.没事去网上找了找答案. 网上流传很广的是一个网上售票系统讲解.转发过来.已经不知道原文到底是出自哪里了. Java中有两种实现多线程的方式.一是直接继承Thre ...
- jsp中两种include的区别【转】
引用文章:http://www.ibm.com/developerworks/cn/java/j-jsp04293/ http://www.cnblogs.com/lazycoding/archive ...
随机推荐
- Oracle导出空表(从来都没有用过的表)
Oracle11g默认对空表不分配segment,故使用exp导出Oracle11g数据库时,空表不会导出! .设置deferred_segment_creation参数为FALSE后,无论是空表还是 ...
- lintcode : 平衡二叉树
题目 平衡二叉树 给定一个二叉树,确定它是高度平衡的.对于这个问题,一棵高度平衡的二叉树的定义是:一棵二叉树中每个节点的两个子树的深度相差不会超过1. 样例 给出二叉树 A={3,9,20,#,#,1 ...
- JS中用execCommand("SaveAs")保存页面兼容性问题解决方案
开发环境:ASP.NET MVC,其他环境仅供参考. 问题描述:在开发中遇到这样的需求,保存页面,通常使用JavaScript的saveAs进行保存,各浏览器对saveAs支持,见下表. 代码一:初始 ...
- 69. Sqrt(x)
题目: Implement int sqrt(int x). Compute and return the square root of x. 链接: http://leetcode.com/pr ...
- Java API —— 多线程(2)
1.JDK5中Lock锁的使用 虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对 ...
- [转]useradd 与adduser的区别
转自:Deit_Aaron的专栏 添加用户:useradd -m 用户名 然后设置密码 passwd 用户名 删除用户:userdel -r 用户名 1. 在root权限下,useradd只是 ...
- NFC(2)NFC、蓝牙和红外之间的差异
NFC(2)NFC.蓝牙和红外之间的差异表
- html5 touch事件实现触屏页面上下滑动(二)
五一小长假哪都没去,睡了三天,今天晕晕沉沉的投入工作了,但还是做出了一点点效果 上周用html5的touch事件把简单的滑动做出来了,实现了持续页面上下滑动的效果,参考之前 的文章及代码html5 t ...
- showdialog()与show的区别
showdialog就是显示有模式的窗体,showdialog后面的语句不会执行,直到显示的窗体被关闭. show就是无模式的窗体,显示窗体后不论窗体是否关闭都执行show后面的语句. ------- ...
- chrome下float元素下input选中内容bug
今天在写一个小demo的时候,发现chrome下一个很奇怪的bug. 我的代码如下: <!DOCTYPE html> <html lang="en"> &l ...