天天看點

[iOS] Objective-C的單件模式

首先,蘋果官方文檔給出了單件模式的例子,代碼見本文最後。 其方式是重寫release,retain,retainCount,autoRelease,allocWithZone和copyWithZone等方法。

1 重寫allocWithZone和copyWithZone的目的是外部在多次調用alloc的時候,内部能夠確定對象隻建立了一次。 2 重寫release、retain、autorelease、retainCount避免單件對象被外部釋放。(官方文檔的舊版本沒有重寫這些方法導緻對象有可能被Over-Release,即多次release,導緻崩潰)

 兩個缺點: 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;
}
           

附官方單件模式的代碼

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;
}
           
[iOS] Objective-C的單件模式