OC中两种单例实现方式

写在前面
前两天探索了一下C++ 的单例,领悟深刻了许多。今天来看看OC中的单例又是怎么回事。查看相关资料,发现在OC中一般有两种实现单例的方式,一种方式是跟C++ 中类似的常规实现方法,另一种是利用GCD来实现的。接下来分别看看这两种单例实现方式是怎么做的

常规实现

与C++中的相似,在OC中实现单例需要满足以下条件:

  1. 设计一个私有的构造方法

  2. 设计一个私有的,本类的对象

  3. 设计一个类方法,作为2中类对象的全局访问点
    接下来我们逐个解决上述3个条件。
    首先,将构造函数设计为私有的。在OC中,对象的创建包括两个步骤:内存申请(alloc)和初始化(init)。也就是说,如果我们希望构造函数私有,那么我们要自己定义alloc方法,使得每次调用该方法,都返回条件2中的对象。在OC中,调用alloc时,alloc实际上是调用allocWithZone这个方法来申请内存的,因此,我们在设计单例的时候,要重写这个方法。另外,我们还要保证使用copy复制单例中的对象时,返回的也是步骤2中的对象,而不会重新创建,因此,我们还要重写copyWithZone这个方法。具体代码如下
    .h文件:

  1. //
  2. // Singleton.h
  3. // Singleton
  4. //
  5. #import <Foundation/Foundation.h>
  6. @interface Singleton : NSObject
  7. //类方法
  8. + (Singleton *) getInstance;
  9. @end

.m文件

  1. //
  2. // Singleton.m
  3. // Singleton
  4. //
  5. #import "Singleton.h"
  6. @implementation Singleton
  7. //在.m文件中声明静态的类实例,不放在.h中是为了让instance私有
  8. static Singleton* instance = nil;
  9. //提供的类唯一实例的全局访问点
  10. //跟C++中思路相似,判断instance是否为空
  11. //如果为空,则创建,如果不是,则返回已经存在的instance
  12. //不能保证线程安全
  13. +(Singleton *) getInstance{
  14. if (instance == nil) {
  15. instance = [[Singleton alloc] init];//调用自己改写的”私有构造函数“
  16. }
  17. return instance;
  18. }
  19. //相当于将构造函数设置为私有,类的实例只能初始化一次
  20. +(id) allocWithZone:(struct _NSZone*)zone
  21. {
  22. if (instance == nil) {
  23. instance = [super allocWithZone:zone];
  24. }
  25. return instance;
  26. }
  27. //重写copy方法中会调用的copyWithZone方法,确保单例实例复制时不会重新创建
  28. -(id) copyWithZone:(struct _NSZone *)zone
  29. {
  30. return instance;
  31. }
  32. @end

main函数文件

  1. // main.m
  2. // Singleton
  3. //
  4. #import <Foundation/Foundation.h>
  5. #import "Singleton.h"
  6. int main(int argc, const char * argv[]) {
  7. @autoreleasepool {
  8. // insert code here...
  9. //用getInstance方法创建实例1、2并打印内容
  10. Singleton *singleton1 = [Singleton getInstance];
  11. NSLog(@"singleton1 = %@.", singleton1);
  12. Singleton *singleton2 = [Singleton getInstance];
  13. NSLog(@"singleton2 = %@.", singleton2);
  14. //用alloc+init创建实例3并打印内容
  15. Singleton *singleton3 = [[Singleton alloc] init];
  16. NSLog(@"singleton3 = %@.", singleton3);
  17. //用alloc+init创建实例4,打印copy后的内容
  18. Singleton *singleton4 = [[Singleton alloc] init];
  19. NSLog(@"singleton4 = %@.", [singleton4 copy]);
  20. }
  21. return 0;
  22. }
  23. /

结果

可以看到,所有的是咧地址都是相同的,也就是或,返回的是同一个地址

GCD方式的单例

GCD是苹果提供的一种多线程的实现方案。使用GCD,用户不用手动管理线程的生命周期,非常方便。GCD提供了一个多线程下,一段代码只被执行一次的方式:dispath_once。这种方式是线程安全的。代码如下,(其余代码与常规方式相同,不再复制)

  1. //使用gcd中的dispatch_once()方法,函数的第二个参数是一个代码段,告诉gcd我们要做的事情是什么
  2. +(Singleton *) getInstance{
  3. static dispatch_once_t onceToken;
  4. dispatch_once(&onceToken, ^{
  5. instance = [[self alloc]init];
  6. });
  7. return instance;
  8. }
  9. //使用gcd的dispatch_once()方法,在传入的代码段中,调用父类的内存申请函数
  10. +(id) allocWithZone:(struct _NSZone*)zone
  11. {
  12. static dispatch_once_t onceToken;
  13. dispatch_once(&onceToken, ^{
  14. instance = [super allocWithZone:zone];
  15. }); return instance;
  16. }

结果如下:

这个结果也证明了,最后创建的类的实例只有一个

OC中两种单例实现方式的更多相关文章

  1. Hibernate中两种获取Session的方式

    转自:https://www.jb51.net/article/130309.htm Session:是应用程序与数据库之间的一个会话,是hibernate运作的中心,持久层操作的基础.对象的生命周期 ...

  2. hadoop中两种上传文件方式

    记录如何将本地文件上传至HDFS中 前提是已经启动了hadoop成功(nodedate都成功启动) ①先切换到HDFS用户 ②创建一个user件夹 bin/hdfs dfs -mkdir /user ...

  3. Hibernate中两种删除用户的方式

    第一种,是比较传统的,先根据主键列进行查询到用户,在进行删除用户 //删除数据 public void deleteStudent(String sno) { init() ; Student qu ...

  4. Java中两种实现多线程方式的对比分析

    本文转载自:http://www.linuxidc.com/Linux/2013-12/93690.htm#0-tsina-1-14812-397232819ff9a47a7b7e80a40613cf ...

  5. mybatis中两种取值方式?谈谈Spring框架理解?

    1.mybatis中两种取值方式? 回答:Mybatis中取值方式有几种?各自区别是什么? Mybatis取值方式就是说在Mapper文件中获取service传过来的值的方法,总共有两种方式,通过 $ ...

  6. FMX有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法(firemonkey messaging)

    看FMX代码,发现有两种消息处理的实现方式,一种是用TMessageManager来实现自定义的消息,另外一种象TEdit中的实现,直接声明消息方法.   早前,看过文章说TMessageManage ...

  7. 【Java】设计模型-五种单例模型

    一. 什么是单例模式 只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计. 单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在. 单例模式有很多好处,它能够 ...

  8. Java中有两种实现多线程的方式以及两种方式之间的区别

    看到一个面试题.问两种实现多线程的方法.没事去网上找了找答案. 网上流传很广的是一个网上售票系统讲解.转发过来.已经不知道原文到底是出自哪里了. Java中有两种实现多线程的方式.一是直接继承Thre ...

  9. jsp中两种include的区别【转】

    引用文章:http://www.ibm.com/developerworks/cn/java/j-jsp04293/ http://www.cnblogs.com/lazycoding/archive ...

随机推荐

  1. 546C. Soldier and Cards

    题目链接 题意 两个人玩扑克,共n张牌,第一个人k1张,第二个人k2张 给定输入的牌的顺序就是出牌的顺序 每次分别比较两个人牌的第一张,牌上面数字大的赢,把这两张牌给赢的人,并且大的牌放在这个人的牌最 ...

  2. lintcode:strStr 字符串查找

    题目: 字符串查找 字符串查找(又称查找子字符串),是字符串操作中一个很有用的函数.你的任务是实现这个函数. 对于一个给定的 source 字符串和一个 target 字符串,你应该在 source ...

  3. MySQL错误代码大全【转载】

    B.1. 服务器错误代码和消息 服务器错误信息来自下述源文件: 错误消息信息列在share/errmsg.txt文件中."%d"和"%s"分别代表编号和字符串, ...

  4. java小程序:求完全数

    如果一个数等于它的不包括自身的所有因数之和,那么这个数就叫完全数.例如,6的不包括自身的所有因数为1,2,3,而且6=1+2+3,所以6是完全数. 大约2200多年前,欧几里德提出:如果2n-1是质数 ...

  5. SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)

    转载:http://itindex.net/detail/50710-springaop-controller-service 从业近二,三年了,第一次写博客,平时做做脚手架或者架构一些基础框架然后给 ...

  6. java retention注解

    Retention注解 Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值:1.RetentionPolicy.SOURCE —— 这种类型的Annotations只在源 ...

  7. iOS iOS7越狱

    1.使用盘古越狱工具 (或者PP助手) 2.越狱成功后需要安装Apple File Conduit “2”,用于替代afc2add插件 3.安装AppSync插件 (绕过系统验证,随意安装.运行破解的 ...

  8. Java解压上传zip或rar文件,并解压遍历文件中的html的路径

    1.本文只提供了一个功能的代码 public String addFreeMarker() throws Exception { HttpSession session = request.getSe ...

  9. kail新手安装

    Kali Linux下载链接:http://mirrors.ustc.edu.cn/kali-images/kali-2.0/ (ps:建议用国内镜像源下载,速度有保证) Kali Linux安装之后 ...

  10. 伪分布模式下使用java接口,访问hdfs

    package com.bq.pro; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import ...