类簇
2017-11-18 本文已影响24人
vincentgemini
类簇(Class Clusters)是抽象工厂模式在iOS下的一种实现,Function中,很多常用类,如NSString、NSArray、NSDictionary以及NSNumber都运作在这一模式下,它是接口简单性和扩展性的权衡体现,在完全不知情的情况下,偷偷隐藏了很多具体的实现类,只暴露出简单的接口。
以NSArray做为说明,先看一段测试代码,说明一点,以下测试是在XCode9中完成的,因为在不同的版本,结果可能会不同:
测试代码.png 输出信息.png通过以上测试可以得到一些结论:
1、NSArray和NSMutableArray可能是通过一个工厂类创建了相同的对象__NSPlacehodlerArray;
2、无论NSArray和NSMutableArray被创建多少次,对象类型相同,地址相同,而且NSArray和NSMutableArray创建出来的对象永远都只相差16位;
3、NSArray和NSMutableArray在通过init方法后,会创建出新的对象,而且发现NSArray不同的初始化也会创建不同的对象;
4、NSArray只要通过init初始化的是空对象,那么永远都是相同对象;
通过上面的结论,大胆猜测NSArray和NSMutableArray的实现:
static __NSPlacehodlerArray *getPlaceholderForNSArray() {
static __NSPlacehodlerArray *instanceForNSArray;
if (!instanceForNSArray) {
instanceForNSArray = [[__NSPlacehodlerArray alloc] init];
}
return instanceForNSArray;
}
static __NSPlacehodlerArray *getPlaceholderForNSMutableArray() {
static __NSPlacehodlerArray *instanceForNSMutableArray;
if (!instanceForNSMutableArray) {
instanceForNSMutableArray = [[__NSPlacehodlerArray alloc] init];
}
return instanceForNSMutableArray;
}
static __NSArray0 *getNSArray0ForNSArray() {
static __NSArray0 *instanceForNSArray;
if (!instanceForNSArray) {
instanceForNSArray = [[__NSArray0 alloc] init];
}
return instanceForNSArray;
}
// NSArray实现
+ (id)alloc
{
if (self == [NSArray class]) {
return getPlaceholderForNSArray()
}
}
// NSMutableArray实现
+ (id)alloc
{
if (self == [NSMutableArray class]) {
return getPlaceholderForNSMutableArray()
}
}
// __NSPlacehodlerArray实现
- (id)init
{
if (self == getPlaceholderForNSArray()) {
self = getNSArray0ForNSArray();
}
else if (self == getPlaceholderForNSMutableArray()) {
self = [[__NSArrayM alloc] init];
}
return self;
}
- (id)initWithObject:(ObjectType)object
{
if (self == getPlaceholderForNSArray()) {
self = [[__NSSingleObjectArrayI alloc] initWithObject:object];
}
else if (self == getPlaceholderForNSMutableArray()) {
self = [[__NSArrayM alloc] initWithObject:object];
}
return self;
}
不仅是NSArray,在Foundation中如NSString, NSDictionary, NSSet等区分可变和不可变版本的类,空实例对象都是静态对象,(NSString的空实例对象是常量区的@"")。