iOS开发-单例模式

版权所有,禁止匿名转载;禁止商业使用。

单例模式是一种非常常见的设计模式,之前文章中UIApplication就是一种典型的单例模式,单例理解起来叶很简单,就不是不管如果访问始终只有一个实例化对象,定义全局共享的变量,如果对象是空则初始化一个对象,如果对象已经存在则使用已经实例化的对象。单例设计模式的作用是使得这个类的一个对象成为系统中的唯一实例,因此需要用一种唯一的方法去创建这个对象并返回这个对象的地址。下面有一张苹果官网的图片可以参考一下:


 


定义一个Food类,大家共享同一个食物,定义一个静态变量,一个实例方法:


static Food *sharedFoodObj=nil;
+(Food *)sharedFood{
    if (!sharedFoodObj) {
        sharedFoodObj=[[Food alloc]init];
    }
    return sharedFoodObj;
}

执行以下代码,最后发现两个实例对象food和foodNext地址是一样的:


Food  *food=[Food sharedFood];
    Food  *foodNext=[Food sharedFood];
    NSLog(@"共享地址:%p-共享地址:%p",food,foodNext);

如果每次都遵守规则调用sharedFood方法,单例模式算是完成了,但是对象是可以实例化的,看一段下面的代码:


Food  *food=[Food sharedFood];
    Food  *foodInit=[[Food alloc]init];
    NSLog(@"共享地址:%p-实例地址:%p",food,foodInit);

food和foodInit的地址是不一样,这个时候我们需要动手改造以下改成的方法,让实例化对象的出来的地址也是一样的,这个时候需要重写 allocWithZone方法: 


+(Food *)sharedFood{
  if (!sharedFoodObj) {
    sharedFoodObj=[[super allocWithZone:NULL]init];
  }
  return sharedFoodObj;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
  return [self sharedFood];
}

如果对象拷贝的时候也需要是同一对象的话,可以加一个方法:


+(id)copyWithZone:(struct _NSZone *)zone{
    return [self sharedFood];
}

如果


+(Food *)sharedFood{
    @synchronized(self){
        if (!sharedFoodObj) {
            sharedFoodObj=[[Food alloc]init];
        }
    }
    return sharedFoodObj;
}

苹果Mac OS 10.6和iOS4.0后引入了GCD,利用GCD(Grand Central Dispatch)和ARC(Automatic Reference Counting)实现单例,这个时候我们可以通过dispatch_once简单的实现,代码如下:


+ (instancetype)sharedInstance
{
  static Food *sharedFoodObj = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedFoodObj =[[super allocWithZone:NULL]init];
  });
  return sharedFoodObj;
}

Food.m中的代码:


//
//  Food.m
//  Demo
//http://www.cnblogs.com/xiaofeixiang
//  Created by keso on 15/2/8.
//  Copyright (c) 2015年 keso. All rights reserved.
//
#import "Food.h"
@implementation Food
static Food *sharedFoodObj=nil;
+(Food *)sharedFood{
  if (!sharedFoodObj) {
    sharedFoodObj=[[super allocWithZone:NULL]init];
  }
  return sharedFoodObj;
}
//
+(id)copyWithZone:(struct _NSZone *)zone{
  return [self sharedFood];
}
- (id)copyWithZone:(NSZone *)zone
{
  return self;
}
+ (instancetype)sharedInstance
{
  static Food *sharedFoodObj = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedFoodObj =[[super allocWithZone:NULL]init];
  });
  return sharedFoodObj;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
  return [self sharedInstance];
}
@end

iOS的单例通过以上方式可以实现,网上有些文章实现单例用了七个方法,不过自从有了ARC之后,有些方法Apple已经不需要重写,说一个题外话,昨天有个博客园的园友只字不改抄袭了我的文章,文章下面说明栏也说明过了(博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用),本人是自己辛苦所得,抄袭转载麻烦留一个链接,技术文章技术人看,做一个技术人需要有些底线~


0 0
登录后参与讨论。点击登录