类簇

类簇是Foundation框架中广泛使用的设计模式。将一些私有、具体的子类组合在一个公共的、抽象的超类下面,以这种方法来组织类可以简化一个面向对象框架的公开架构,而又不减少功能的丰富性。
类簇是属于工厂设计模式的

举例应用

OC中的Number 可以表示很多类型的数值对象。其其实是一个抽象的基类,声明的方法一般都是操作其子类。 因为不同的数值类型可能有很多特征(可以从一个类型转换为另外一个类型,例如,可以描述其为字符串),所以在Number类里有很多方法可以用来描述这些特征,但是他们因为是不同类型,其存储的需求一定是不同的,所以Number类中并不声明实例变量去存储数值,在子类中声明这样的实例变量并在Number的API中获得

我们一般通过一下方法

NSNumber *aChar = [NSNumber numberWithChar:’a’];
NSNumber *anInt = [NSNumber numberWithInt:1];
NSNumber *aDouble = [NSNumber numberWithDouble:1.0];

其实生成的每个对象都属于不同的子类,虽然每个对象的类成员是隐藏的,但是抽象基类声明的接口是公共的。

常见公共基类类簇


也存在两个抽象公共类为类簇声明接口,但他们明确说明了两个点如何协作,其中一个公共的点声明所有类簇中对象都能响应的方法,另一点声明方法仅适合类簇对象内容能被修改的。

类簇的子类

如果发现类簇并没有提供你的问题的方法,这是可能需要一个子类。

  • 需要创建一个文件存储而不是内存存储的数组对象,,就像要改变NSArray类簇的底层存储机制,那么必须创建一个子类
  • 假设app需要在修改一些数据时提醒,此时没创建一个简单的类,将一个数据对象的基础框架定义。这个类的对象可以介入消息修改数据,拦截信息,代理,然后转发给嵌入式数据对象

总之,如果需要管理对象的存储就创建一个真正的子类。否则创建一个复合对象,一个标准的基础框架对象嵌在你自己的设计的一个对象。

创建类簇的子类

创建类簇的子类需要:

  1. 继承类簇的虚基类
  2. 定义自己的存储
  3. 重写父类的初始化方法
  4. 重写父类的原始方法

因为类簇的虚基类在类簇中仅有的公共访问点,所以只能继承虚基类,因此虽然可以继承其接口但是不能继承其实例变量,子类必须声明自己需要的实例变量,而且必须重写继承所有的方法,来访问对象的实例变量。这些方法叫做基元方法

一个类的基元方法来自接口的底层。
例如,NSArray通过两个基元方法count:和objectAtIndex:存储数据并且通过下标访问,作为基础其它导出方法可以实现。
因此,必须确保重写继承的基元方法,来去保证其它继承的所有派生方法可以正常运转,即使我们没有重写其它方法

子类应该声明其init、 +className方法(如果其有实例变量的话),应该在自己的初始化方法中调用基类的指定初始化器。应该重写所有的其它继承的初始化方法并且实现,使其有合理的行为方法,

组合类

通过在自己设计的对象中植入类簇对象。创建一个组合复合对象。可以依靠类簇对象的功能,来截取复合对象要处理的消息。

复合对象继承自类簇的虚基类,作为子类,必须重写基类的基元方法,也可以重写导出方法(非必须).

示例:
测试验证对数组中对象的修改 保证其有效性

@interface ValidatingArray : NSMutableArray

{
    NSMutableArray *embeddedArray;
}

+ (instancetype)validatingArray;

- (instancetype)init;

- (NSUInteger)count;

- (id)objectAtIndex:(NSUInteger)index;

- (void)addObject:(id)anObject;

- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;

- (void)removeLastObject;

- (void)removeObjectAtIndex:(NSUInteger)index;

- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;

@end


#import "ValidatingArray.h"

@implementation ValidatingArray

+ (instancetype)validatingArray {
    return [[self alloc] init];
}

- (instancetype)init {
    if (self = [super init]) {
        embeddedArray = [NSMutableArray array];
    }
    return self;
}

- (NSUInteger)count {
    return embeddedArray.count;
}

- (id)objectAtIndex:(NSUInteger)index {
    return [embeddedArray objectAtIndex:index];
}

- (void)addObject:(id)anObject {
    // 自定义验证代码
    [embeddedArray addObject:anObject];
}

- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
    // 自定义验证
    [embeddedArray replaceObjectAtIndex:index withObject:anObject];
}

- (void)removeLastObject {
    // 自定义验证
    [embeddedArray removeLastObject];
}

- (void)removeObjectAtIndex:(NSUInteger)index {
    // 自定义验证
    [embeddedArray removeObjectAtIndex:index];
}

- (void)insertObject:(id)anObject atIndex:(NSUInteger)index {
    // 自定义验证
    [embeddedArray insertObject:anObject atIndex:index];
}

@end