iOS singleton
Singleton(单例模式)是一种很常见的模式,仔细看了下。其实OC里面和java 还是有些不同的。 不同体现在,java 可以将构造方法(相当于oc 里面 alloc init)设置成为 private(私有),这样当别的地方去实例化一个对象的时候就发现无法使用构造方法了,从而使用 getInstence(或者其它的)去实例化一个新的对象。这样一来在getInstence里面做一些操作即可以保证单例类。
而oc里面是无法私有alloc 方法,所以当我们写了相对应的类方法 getInstence,别的地方还是可以利用 alloc init 出新的对象出来的。所以在oc里面还需要对 alloc 方法进行处理。当然oc里面还有别的比如 copy。(考虑到 ARC 就不说一些 release 方法了)
下面是我自己写的一个单例类:
h文件,比较简单就是基本的东西 name 是为了测试添加的
#import <Foundation/Foundation.h>
@interface PersonFactory : NSObject
@property(nonatomic,strong)NSMutableString *name;
+(id)defaultPersonFactory;
@end
m文件,
#import "PersonFactory.h"
@implementation PersonFactory
static PersonFactory *sharedPersonFactory = nil;
//重写allocWithZone方法
+(id)allocWithZone:(NSZone *)zone{
@synchronized (self) {
if (sharedPersonFactory == nil) {
sharedPersonFactory = [super allocWithZone:zone];
}
if (sharedPersonFactory.name == nil) {
sharedPersonFactory.name = [[NSMutableString alloc]init];
}
[sharedPersonFactory.name setString:@"alloc!"];
return sharedPersonFactory;
}
}
+(id)defaultPersonFactory{
if (sharedPersonFactory == nil) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedPersonFactory = [[self alloc]init];
if (sharedPersonFactory.name == nil) {
sharedPersonFactory.name = [[NSMutableString alloc]init];
}
[sharedPersonFactory.name setString: @"test"];
});
}
return sharedPersonFactory;
}
-(id)copyWithZone:(NSZone *)zone{
return self;
}
@end
测试代码:
-(void)testSingleton{
PersonFactory *personFac1 = [PersonFactory defaultPersonFactory];
NSLog(@"perFac1 name is %@ %p", personFac1.name, personFac1);
PersonFactory *personFac2 = [[PersonFactory alloc]init];
NSLog(@"perFac2 name is %@ %p", personFac2.name, personFac2);
PersonFactory *personFac3 = [personFac1 copy];
NSLog(@"perFac3 name is %@ %p", personFac3.name, personFac3);
}
测试输出log:
perFac1 name is test 0x7b8a8ad0
perFac2 name is alloc! 0x7b8a8ad0
perFac3 name is alloc! 0x7b8a8ad0
可能存在的问题
- 刚刚说的重写重alloc/copy方法,为什么没有重写?
因为 alloc 方法调用的还是 allocWithZone 方法,copy也一样,如果只重写 alloc,还是可以通过 allocWithZone 来构造出新的对象。 - synchronized 只是保证只有同一时间只有一个操作对当前 self的操作。
- dispatch_once 代表里面的代码只会执行一次。
- 为什么不直接重写 alloc 或者 allocWithZone 方法??
我自己想的是因为不能私有化 alloc/allocWithZone ,这样用 alloc/allocWithZone 根本就不知道这个类是单例的,解释好牵强…
其它问题:
在NSObject 的h文件里找到
- (id)copy;
- (id)mutableCopy;
+ (id)copyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
可以看到的是copyWithZone是类方法,为什么在调用 copy 方法的时候会去找对象方法 copyWithZone ?
www.rainkong.net