类簇模式
举个例子,UIButton类的一个类方法:
+ (instancetype)buttonWithType:(UIButtonType)buttonType;
这个方法可以帮助我们“生产”出不同样式的button。
如果我们只有一个button类,要实现上面那个buttonWithType方法,可能就需要在drawRect方法中做一些判断:
- (void)drawRect:(CGRect)rect{
if(_type == TypeA){
//Draw TypeA Button
}
else if(_type == TypeB){
//Draw TypeB Button
}
//..........
}
这样的方式显得非常笨重,如果不知drawRect方法要求对类型做判断,还有很多别的方法内要求判断,那么会显得非常麻烦。这种情况下,使用类簇会非常适合,不会暴露多余的接口,方法的实现也比较灵活。
创建一个类簇
创建时类簇的写法大致如下:
#import "TestButton.h"
@interface TypeAButton:TestButton
@end
@implementation TypeAButton
@end
@interface TypeBButton : TestButton
@end
@implementation TypeBButton
@end
@implementation TestButton
- (instancetype)initWithButtonType:(TestButtonType)type
{
switch (type) {
case ButtonTypeA:
return [TypeAButton new];
break;
case ButtonTypeB:
return [TypeBButton new];
default:
return [TestButton new];
}
}
当我们进行类型判断的时候,还是要多加注意。在这种情况下isMemberOfClass可能永远不会成立,测试代码如下:
TestButton *newButton = [TestButton testButtonWithType:ButtonTypeA];
if ([newButton isKindOfClass:[TestButton class]]) {
NSLog(@"YES,it is kind of TestButton Class");
}
else{
NSLog(@"NO");
}
if ([newButton isMemberOfClass:[TestButton class]]) {
NSLog(@"YES,it is member of TestButtonClass");
}
else{
NSLog(@"NO");
}
打印结果
系统中的类簇
大部分的集合类型都是采用类簇模式,比如NSArray及可变版本NSMutableArray。所以有两个基本的抽象类,一个是不可变数组类,另一个是可变数组类。他们依然属于类簇,不过两个基本抽象类都暴露在了interface中。
不可变的那个类定义了数组的所有通用方法,可变的类只定义了可变数组可以调用的方法。这样的好处在于,这两个类背后可以有大量相同的代码可以复用,也可以方便进行可变拷贝和不可变拷贝。
在实际数组的创建过程中,比如
NSArray *array = [NSArray alloc] init];
实际上并不是创建了一个NSArray类,而是一个placeholder array 被创建,这个placeholder array之后会被转换为NSArray类簇中一个具体的类。
所以以下if代码,永远都不会进入:
NSArray *testArray = [[NSArray alloc] init];
if ([testArray class] == [NSArray class]) {
NSLog(@"YES");
}
所以判断类型还是使用isKindOf,我想在理解了类簇的原理之后都能知道为什么。
写类簇的注意<span id="jump">类簇的注意</span>
- 1 子类必须继承自抽象的父类。比如上面代码中要写Testbutton中这个类簇的子类,那么父类比如是TestButton,而不能是TypeBButton或TypeAButton。
- 2 父类中的声明的关键方法,子类中必须要写相应方法的实现。
- 3 对于容器类的类簇,比如NSArray类,需要自己实现类的“储存”特性,这可能与设计初衷有点违背,因为NSArray类设计就是用来储存对象的。
书中原话是这样:** a good choice of object to use to hold the instance of a custom array subclass would be an NSArray itself**
不知道怎么样理解更加正确。
总结
- 1 类簇模式可以用来隐藏一些类的实现细节。
- 2 类簇模式在系统框架中使用的非常广泛,需要注意类别检查。
- 3 写类簇的注意
网友评论