Objective-C 中的单例

其实对于单例,在程序开发中非常的常见。
最近我也对单例进行了一些更细致的研究。
在我的程序中,单例一般是这么去写的:
+ (DataSource *)shareInstance
{
    static DataSource *instance = nil;
    if (instance == nil)
    {
        instance = [[DataSource alloc] init];
    }
    return instance;
}

在我做过的十几个软件中,一直都是这么去写的。
但是在我前段时间看书的过程中,发现跟书中的例子不太一样,所以做了一下研究。

发现,这样的单例是不可靠的。因为如果开发者一直调用 [DataSource shareInstance] 当然没有问题, 但是如果有人调用 [ DataSource alloc] 这样的方法,就会出现多个对象。
所以,我们需要实现“严格”意义的单例。

需要克服两个障碍:
1. 发起调用的对象不能以其他分配方式实例化单例对象。
2.对单例对象实例化的限制应该与引用计数内存模型共存。

下面我们看一下官方给出的单例模式的例子

static MyGizmoClass *sharedGizmoManager = nil;  
  
+ (MyGizmoClass*)sharedManager  
{  
    if (sharedGizmoManager == nil) {  
        sharedGizmoManager = [[super allocWithZone:NULL] init];  
    }  
    return sharedGizmoManager;  
}  
  
+ (id)allocWithZone:(NSZone *)zone  
{  
    return [[self sharedManager] retain];  
}  
  
- (id)copyWithZone:(NSZone *)zone  
{  
    return self;  
}  
  
- (id)retain  
{  
    return self;  
}  
  
- (NSUInteger)retainCount  
{  
    return NSUIntegerMax;  //denotes an object that cannot be released  
}  
  
- (void)release  
{  
    //do nothing  
}  
  
- (id)autorelease  
{  
    return self;  
}

他的方式是重写release,retain,retainCount,autoRelease,allocWithZone和copyWithZone等方法。
1 重写allocWithZone和copyWithZone的目的是外部在多次调用alloc的时候,内部能够确保对象只创建了一次。
2 重写release、retain、autorelease、retainCount避免单件对象被外部释放。

两个缺点:
A 隐藏了在对象生命周期管理时出现的bug。
    对对象的引用出错的原因必然是程序本身的错误,隐藏对象的引用计数错误就是隐藏了应用程序的错误。
    从工程角度上讲,崩溃要比程序的逻辑错误容易定位。
    解决方法:建议在release、retain、autorelease里面做一些内部的调用次数监控,一旦发现外部调用不平衡就发出警告。
B 对象可以被多次init。
    多次调用init导致错误的可能性还是有的,这种错误包括重复加载某些资源降低性能。
    解决方法:重写init并在内部判重就可以了。
C 多线程安全
    解决方法:在sharedManager中加入同步代码块,代码:

+ (MyGizmoClass*)sharedManager  
{  
    @synchronized(self) {  
        if (sharedGizmoManager == nil) {  
            sharedGizmoManager = [[super allocWithZone:NULL] init];  
        }  
    }  
    return sharedGizmoManager;  
}  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值