原帖地址:http://www.cocoachina.com/newbie/basic/2009/0611/254.html
1、普通方法
如果你准备写一个类,希望保证只有一个实例存在,同时可以得到这个特定实例提供服务的入口,那么可以使用单态设计模式。单态模式在Java、C++中很常用,在Cocoa里,也可以实现。
由于自己设计单态模式存在一定风险,主要是考虑到可能在多线程情况下会出现的问题,因此苹果官方建议使用以下方式来实现单态模式:
-
static MyGizmoClass *sharedGizmoManager = nil; + (MyGizmoClass*)sharedManager { @synchronized(self) { if (sharedGizmoManager == nil) { [[self alloc] init]; // assignment not done here } } return sharedGizmoManager; } + (id)allocWithZone:(NSZone *)zone { @synchronized(self) { if (sharedGizmoManager == nil) { sharedGizmoManager = [super allocWithZone:zone]; return sharedGizmoManager; // assignment and return on first allocation } } return nil; //on subsequent allocation attempts return nil } - (id)copyWithZone:(NSZone *)zone { return self; } - (id)retain { return self; } - (unsigned)retainCount { return UINT_MAX; //denotes an object that cannot be released } - (void)release { //do nothing } - (id)autorelease { return self; }
2、使用GCD创建单例
创建一个新类,命名它为LibraryAPI,设置父类为NSObject.打开LibraryAPI.h,用如下代码替换它的内容
@interfaceLibraryAPI : NSObject + (LibraryAPI*)sharedInstance; @end
现在打开LibraryAPI.m,在@implementation 那一行后面插入下面的方法:
+ (LibraryAPI*)sharedInstance { // 1 static LibraryAPI *_sharedInstance = nil; // 2 static dispatch_once_t oncePredicate; // 3 dispatch_once(&oncePredicate, ^{ _sharedInstance = [[LibraryAPI alloc] init]; }); return _sharedInstance; }
在这个简短的方法中,有一些需要需要注意的点:1.声明一个静态变量去保存类的实例,确保它在类中的全局可用性。2.声明一个静态变量dispatch_once_t ,它确保初始化器代码只执行一次3.使用Grand Central Dispatch(GCD)执行初始化LibraryAPI变量的block.这 正是单例模式的关键:一旦类已经被初始化,初始化器永远不会再被调用。下一次你调用sharedInstance的时候,dispatch_once块中的代码将不会执行(因为它已经被执行了一次),你将得到原先已经初始化好的实例。