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]; ,这会让 继续初始化执行正确的初始化之前的会话。
类族的写法
时间: 2024-10-04 00:45:05