类族的写法

http://mdsa.51cto.com/art/201507/484133_4.htm


这个模式的精妙的地方在于,调用者可以完全不管子类,事实上,这可以用在设计一个库,可以用来交换实际的返回的类,而不用去管相关的细节,因为它们都遵从抽象超类的方法。

我们的经验是使用类簇可以帮助移除很多条件语句。

一个经典的例子是如果你有为 iPad 和 iPhone 写的一样的 UIViewController 子类,但是在不同的设备上有不同的行为。

比较基础的实现是用条件语句检查设备,然后执行不同的逻辑。虽然刚开始可能不错,但是随着代码的增长,运行逻辑也会趋于复杂。 一个更好的实现的设计是创建一个抽象而且宽泛的 view controller 来包含所有的共享逻辑,并且对于不同设备有两个特别的子例。

通用的 view controller 会检查当前设备并且返回适当的子类。

@implementation ZOCKintsugiPhotoViewController 
 
- (id)initWithPhotos:(NSArray *)photos 
{ 
    if ([self isMemberOfClass:ZOCKintsugiPhotoViewController.class]) { 
        self = nil; 
 
        if ([UIDevice isPad]) { 
            self = [[ZOCKintsugiPhotoViewController_iPad alloc] initWithPhotos:photos]; 
        } 
        else { 
            self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos]; 
        } 
        return self; 
    } 
    return [super initWithNibName:nil bundle:nil]; 
} 
 
@end 
上面的代码的例子展示了如何创建一个类簇。首先,[self isMemberOfClass:ZOCKintsugiPhotoViewController.class] 来避免在子类中重载初始化方法,来避免无限的递归。当 [[ZOCKintsugiPhotoViewController alloc] initWithPhotos:photos] 得到调用的时候之前的检查会变成 true 的,self = nil 是用来移除所有到 ZOCKintsugiPhotoViewController 实例的引用的,它会被释放,按照这个逻辑来检查哪个类应该被初始化。 让我们假设在 iPhone 上运行了这个代码, ZOCKintsugiPhotoViewController_iPhone 没有重载initWithPhotos:,在这个情况下,当执行 self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos]; 的时候,ZOCKintsugiPhotoViewController 会被调用,并且当第一次检查的时候,这样不会让ZOCKintsugiPhotoViewController 检查会变成 false 调用return [super initWithNibName:nil bundle:nil]; ,这会让 继续初始化执行正确的初始化之前的会话。

原文地址:https://www.cnblogs.com/pencilCool/p/4802234.html