单例模式
我的理解:
单例模式是通过类方法创建一个实例化的对象,这个对象具备共享性和唯一性。
之前一直使用的
[UIApplication sharedApplication].delegate
其实就是Appdelegate的一个单例实现。
创建单例模式的注意点
- 线程安全
- 很好满足静态分析器要求
- 和自动引用计数(ARC)兼容
- 只能用创建的类方法获取实例化对象,禁用
alloc init
a - 防止子类调用
- 添加断言,减小调试难度
实际代码及说明
- 线程安全:
如果一个单例在多个类中被调用,会产生竞争(多处都去初始化,不知道要做谁的).因此要使用dispatch_once来操作 - 定义全局的一个当前类的变量,保证静态安全
- 禁用
alloc init
,只使用单例。
下面的代码中,进入[string isEqualToString:@"UserInfoManagerCenter"]
判断一定是不通过的。因为center只能在单例模式中被初始化,否则都是nil,所以使用alloc init一定是返回nil的
//判断当前类
NSString *string = (NSString *)center;//center已经定义为本类的全局变量
if ([string isKindOfClass:[NSString class]] == YES && [string isEqualToString:@"UserInfoManagerCenter"])
- 防止子类调用,不赘述
源码
#import "UserInfoManagerCenter.h"
#define SELFCLASS_NAME BaiduLocationTool
#define SELFCLASS_NAME_STR @"UserInfoManagerCenter"
static UserInfoManagerCenter *center = nil;//定义一个全局的静态变量,满足静态分析器的要求
@implementation UserInfoManagerCenter
+ (instancetype)managerCenter {
static dispatch_once_t predicate;
//线程安全
dispatch_once(&predicate, ^{
center = (SELFCLASS_NAME *)SELFCLASS_NAME_STRY;
center = [[SELFCLASS_NAME alloc] init];
});
// 防止子类使用
NSString *classString = NSStringFromClass([self class]);
if ([classString isEqualToString: SELFCLASS_NAME_STR] == NO)
NSParameterAssert(nil);
return center;
}
- (instancetype)init {
NSString *string = (NSString *)center;
if ([string isKindOfClass:[NSString class]] == YES && [string isEqualToString:SELFCLASS_NAME_STR]) {
self = [super init];
if (self) {
// 防止子类使用
NSString *classString = NSStringFromClass([self class]);
if ([classString isEqualToString:SELFCLASS_NAME_STR] == NO)
NSParameterAssert(nil);
}
return self;
} else
return nil;
}
@end
结果
------- 下面的结果和上述的代码无关-------
可以看到的是,在不同地方使用单例来实例化,得到的对象,地址是一样的。
2.<UserInfoManagerCenter: 0x7fcd72dbacf0>
2016-04-07 11:36:53.103 SingletonPattern[2623:153276] 3.(null)
2016-04-07 11:36:53.106 SingletonPattern[2623:153276] <UserInfoManagerCenter: 0x7fcd72dbacf0>