一 何为单例singleton模式?(what)
保证一个类只有一个实例,并提供一个访问它的全局访问点。
二 何时使用单例模式?(where)
1类只能有一个实例,而且必须从一个为人熟知的访问点对其访问,比如工厂方法。
2这个唯一实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
为什么不用静态全局变量或是类方法呢?
如果一个程序中两个人分别在两个地方定义了相同类型的静态变量。那么一个程序中就会有两个相同的全局对象类型。
类方法提供了共享服务,不用创建其对象就可以访问,资源的唯一实例可以在类方法中进行维护。但是如果累需要被子类化以提供更好的服务,这一方式就不灵活。
三 实现单例模式 (how)
static Singleton *sharedSingleton_=nil;
+(Singleton *)sharedInstance
{
if(sharedSingleton_==nil){
sharedSingleton = [[Singleton alloc]init];
}
return sharedSingleton_;
}
需克服问题:
发起调用的对象不能以其他方式实例化单例对象。否则就可能创建单例类的多个实例。
对单例对象实例化的限制应该与引用计数内存模型共存。
解决:
static Singleton *sharedSingleton_=nil;
+(Singleton *)sharedInstance
{
if(sharedSingleton_==nil){
sharedSingleton = [[super allocWithZone:NULL]init];
}
return sharedSingleton_;
}
用super的原因是,已经在self中重载了基本对象分配方法,需要借用父类来帮助处理底层内存分配的复杂任务
+(id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance] retain];//为什么retain,是有了把Singleton类变得不太严格的一种选择(即允许分配与初始化额外的实例,但shareInstance工厂方法总是返回同一个实例,否则singleton对象可能被破坏)子类可以再次重载retain、release和autorelease方法,实现合适的内存管理。
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (NSUInteger)retain
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax;//4294967295
}
- (void)release
{
//生么也不做
}
- (id)autorelease
{
return self;
}
alloc使用设为NULL的zone来调用allocWithZone:在默认区域为新实例分配内存。
四 子类化单例
如果用以上的方法,不做修改的子类化Singleton时,返回的实例总是Singleton,因为Singleton重载了所有实例化相关的方法。
解决方法:
+(Singleton *)sharedInstance
{
if(sharedSingleton_==nil){
sharedSingleton = [NSAllocateObject([self class],0,NULL) init];
}
return sharedSingleton_;
}
第一个参数是类型,第二个参数是用于索引实例变量的额外字节数总是0,第三个参数用于指定内存中分配的区域一般为NULL表示默认区域。可以通过指定类的类型,用这个函数实例化任何对象。
五 还要注意单例对象的线程安全
@synchoronized()或NSLock或是dispatch_once