9、以“类族模式”隐藏实现细节

​ “类簇”(class cluster)是一种很有用的模式(pattern),可以隐藏“抽象基类”(abstract base class)背后的实现细节。OC的系统框架中普遍使用此模式,大部分的collection类都是类簇,如:UIButtonNSArrayNSMutableArray等:

// 返回的对象,其类型取决于传入的按钮类型(button type)
// 不管返回什么类型的对象,都是继承自同一个基类:UIButton
// 意义:使用者无须关心属于哪个类,和其绘制等实现细节,只须知道如何创建,如何设置,如何使用就好
+ (UIButton *)buttonWithType:(UIButtonType)type; 

// 如果放在同一个类里,你可能会写出这样的代码:
- (void)drawRect:(CGRect)rect {
  if (_type == TypeA) {
    // Draw TypeA button
  } else if (_type == TypeB) {
    // Draw TypeB button
  }
  // 但是当类型和方法越来越多时,这样做救护很麻烦
}

​ 优秀的程序猿会重构为多个子类,把各个按钮所用的绘制方法放到相关子类中去。不过需要用户知道各种子类才行,此时应使用“类簇模式”:可以灵活应对多个类,讲他们的实现细节隐藏在抽象基类后面,以保持接口简洁。用户无须自己创建子类实例,只需调用基类方法来创建即可。

创建类簇:

// .h:声明枚举、属性、方法。。。
// .m:实现初始化方法:工程模式,是创建类簇的方式之一
+ (MOEmployee *)employeeWithType:(MOEmployeeType)type {
  swith (type) {
    case MOEmployeeTypeDeveloper: return [MOEmployeeDeveloper new];
    case MOEmployeeTypeDesigner: return [MOEmployeeDesigner new];
    case MOEmployeeTypeFinance: return [MOEmployeeFinance new];
  }
}
- (void)doWork {
  // 子类们实现各自的工作内容
}
// 子类继承MOEmployee,并实现doWork方法。。。
// 另外注意:
[anEmployee isMemberOfClass:[MOEmployee class]] // 永远为NO!!!

Cocoa里的类簇:

​ 你要是知道NSArray是个类簇,就不会写出下面第一行这样的代码,[anArray class]所返回的类绝对不可能是NSArray类本身!!!

if ([anArray class] == [NSArray class]) {} // 永远为NO!!!
// Array的初始化方法返回的是隐藏的某个内部类型

// 不过可以这样判断是都属于其类簇中
if ([anArray isKindOfClass:[NSArray class]]) {} // YES

​ 想为类簇新增子类,需要遵循几条规则:

  • 子类应该继承自类簇中的抽象基类(如:不可变数组的基类 or 可变数组的基类)

  • 子类应该定义自己的数据存储方式(如:Array子类,可以用Array来存储,Array不会自动保存数据)

  • 子类应当覆写超类文档中指明需要覆写的方法(如:ArraycountobjectAtIndex:

要点:

  • 类簇模式可以把实现细节隐藏在一套简单的公共接口后面

  • 系统框架中经常使用类簇

  • 从类簇的公共抽象基类中继承子类时要当心,若有开发文档,则应首先阅读

Last updated

Was this helpful?