iOS中单例模式的实现

单例是设计模式中用的比较多的一种。在iOS中也经常能见到单例模式的使用。比如 [ UIApplication  sharedApplication ], [ NSUserDefaults  standardUserDefaults ]等等。那么,在我们自己实现一个单例模式的时候需要怎么做以及注意什么问题呢?


单例模式分为两种,一种是只允许存在一个实例,无论通过什么方法创建的时候都只返回同一个实例。另一种就是除了使用单例之外,也允许用户创建其他的实例。第一种如[UIApplication sharedApplication],第二种如[NSFileManager defaultManager]。

一般的单例实现方法

static MySingletonClass *sharedInstance;

+(MySingletonClass *)sharedSingletonClass
{
    if (sharedInstance == nil)
    {
        sharedInstance = [[super allocWithZone:nil] init];
    }
    return sharedInstance;
}

这是一个简单又快捷的方式,但它不是线程安全的。因为当多个线程同时访问它的时候,它可能会被调用多次。那么我们就需要一个方法来保证这个构造方法最多只被调用一次。

线程安全的方式

+(MySingletonClass *)sharedSingletonClass
{
   
    @synchronized(self) {
        if (sharedInstance == nil)
        {
            sharedInstance = [[super allocWithZone:nil] init];
        }
    }
    return sharedInstance;
}

通过使用synchronized关键字来达到线程互斥的目的,这样sharedInstance = [[super allocWithZone:nil]init]就会只调用一次了。

我们保证了线程的同步问题,但是如果我们只想拥有一个实例怎么办呢?因为目前情况下,用户还可以通过其他方式来创建另一个实例。

只有一个实例

为了不让用户自己创建其他的实例,我们需要将其他创建实例的方法都重写一下。

+ (id)allocWithZone:(NSZone *)zone
{
    return [[<span style="font-family: Arial, Helvetica, sans-serif;">MySingletonClass<span style="white-space:pre">	</span>   </span>sharedSingletonClass] retain];
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;[NSFileManager defaultManager]
}

- (id)retain
{
    return self;
}

- (NSUInteger)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

看到这里大家有没有发现我们只重写了allocWithZone而没有重写alloc方法呢,会不会觉得通过alloc还可以创建一个新的实例呢?哈哈,这样想你就错了,因为alloc最终是调用allocwithZone来创建实例的,so,不用担心这个问题了。

另外,不知道大家注意到没有,在sharedSingletonClass里面用的时候[super allockWithZone]而没有用[self alloc],如果使用后者的话会形成死循环哦,因为[self alloc]会调用allockWithZone,但我们重写了这个函数,在这个函数里又调用了sharedSingletonClass。

另外,大家请仔细想想为什么我们需要重写retain、retainCount、release和autoRelease方法呢?

到目前为止,我们基本上可以创建我们想要的单例了。但是在iOS中,引入了ARC,retain和release都不允许在代码中出现,这个时候该怎么办呢,是不是不用重写跟内存相关的代码就可以了呢?

另一种线程同步机制

+(MySingletonClass *)sharedSingletonClass
{
    static dispatch_once_t pred = 0;
    __strong static MySingletonClass *sharedInstance;
    dispatch_once(&pred, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
dispatch_once是指在应用程序的生命周期内,这个方法只被执行一次。

在ARC模式下就不能再重写retain和release相关的函数了,只需要实现面下的即可。需要将retain和release相关的代码去掉,其他的与普通的一样实现即可。因为在ARC环境下不会有显式的retain和release的调用,内存完全由程序来管理,所以不会造成对象被销毁的问题。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值