简介
Class Clusters(类簇)是抽象工厂模式在iOS下的一种实现,众多常用类,如NSString、NSArray、NSDictionary以及NSNumber都运作在这一模式下,它是接口简单性和扩展性的权衡体现,在我们完全不知情的情况下,偷偷隐藏了很多具体的实现类,只暴露出简单的接口。
<span style="font-family:Microsoft YaHei;">-(void)cluster
{
id obj1 = [NSArray alloc];
id obj2 = [NSMutableArray alloc];
id obj3 = [obj1 init];
id obj4 = [obj2 init];
NSLog(@"%@",NSStringFromClass([obj1 class]));
NSLog(@"%@",NSStringFromClass([obj2 class]));
NSLog(@"%@",NSStringFromClass([obj3 class]));
NSLog(@"%@",NSStringFromClass([obj4 class]));
/*
结果:
2016-01-13 20:58:29.455 1fundation框架[2570:230724] __NSPlaceholderArray
2016-01-13 20:58:29.456 1fundation框架[2570:230724] __NSPlaceholderArray
2016-01-13 20:58:29.457 1fundation框架[2570:230724] __NSArray0
2016-01-13 20:58:29.457 1fundation框架[2570:230724] __NSArrayM
*/
}</span>
发现+alloc之后并非生成了我们期望的类实例 而是一个__NSPlaceholderArray的中间对象 后面的-init或者-initWithxx等方法调用都是把消息发送给这个中间对象 再由它做工厂 生成真正的对象。
(这里的__NSArrayI和__NSArrayM分别对应immutable和mutable。)
所以 __NSPlaceholderArray必定用某种方式存储了它是由谁alloc出来这个消息,才能判断是创建哪个类型的数组
而可以测试看得 obj1 obj2的地址是一样的。所以,可以猜测 内部实现应该差不多如下所示
<span style="font-family:Microsoft YaHei;">+(id)alloc
{
if(self == [NSMutableArray class])
{
return getNSMutableArray();
}else if(self == [NSArray class])
{
return getNSArray();
}
}
-(id)init
{
if (self == getNSArray()) {
return [self initNSArray];
}else if(self == getNSMutableArray())
{
return [self initNSMutableArray];
}
}</span>
因此以下代码中:
<span style="font-family:Microsoft YaHei;">id obj1 = [NSArray alloc];
id obj2 = [NSArray alloc];
id obj3 = [NSMutableArray alloc];
id obj4 = [NSMutableArray alloc];</span>
obj1 obj2地址相同 obj3 obj4地址相同。
那么猜测NSDictionary NSSet NSString等是一样的情况。
对NSNumber的猜想
NSNumber可以存储各种类型的数据, Int Float Double。
站在设计者的角度上看,一种方式是把NSNumber作为基类 然后分别实现各自的子类
但是如果子类过多 对于开发者就很麻烦了。
于是 NSNumber中使用类簇的模式,将子类对外封闭,开发者只需要记住一个父类 而实例化相对应的子类。所以可以猜测其内部实现原理:
- (id)initWithBool
{
return [[__NSCFBoolean alloc]init];
}
- (id)initWithLong
{
return [[__NSCFNumber alloc]init];
}
对于开发者:iOS开发中的应用
1.表现和行为完全一样 但是数据源不一样
2.cell的类型不一样
3.应用的兼容,iOS6、7的图片资源不同
- if ([[UIDevice currentDevice]systemMajorVersion] < 7)
- {
- /* iOS 6 and previous versions */
- }
- else
- {
- /* iOS 7 and above */
- }
- /* TestView.h */
- @interface TestView: UIView
- /* Common method */
- - ( void )test;
- @end
- /* TestView.m */
- @implementation TestView
- + (id)alloc
- {
- if ([self class]== [TestView class])
- {
- if ([[UIDevice currentDevice] systemMajorVersion] < 7)
- {
- return [TestViewIOS6 alloc];
- }
- else
- {
- return [TestViewIOS7 alloc];
- }
- }
- else
- {
- return [super alloc];
- }
- }
- - ( void )test
- {}
- @end
- /* TestViewIOS6.m */
- @implementation TestViewIOS6: TestView
- - (void)drawRect: (CGRect)rect
- {
- /* Custom iOS6 drawing code */
- }
- @end
- /* TestViewIOS7.m */
- @implementation TestViewIOS7
- - (void)drawRect: (CGRect)rect
- {
- /* Custom iOS7 drawing code */
- }
- @end