美文网首页
(九) [OC高效系列]尽量使用类族模式来隐藏细节

(九) [OC高效系列]尽量使用类族模式来隐藏细节

作者: 修行猿 | 来源:发表于2016-08-12 20:44 被阅读116次

    1.解读一下标题

    就是将同一类型不同细节的逻辑放在子类中,而基类和所有子类统称为类族。我自己理解的定义,不喜勿喷。

    2.先举一个没有用类族模式的小例子。

    Person类有两个类型 Teacher、Student。当吃饭的时候,显示老师在吃饭和学生在吃饭。代码如下:

    @interface Person : NSObject
    
    @property (nonatomic,copy) NSString *name;
    @property (nonatomic,copy) NSString *num;
    @property (nonatomic,assign) PersonType type;
    + (instancetype)personWithType:(PersonType)type;
    
    - (void)eat;
    
    @end
    
    @implementation Person
    
    + (instancetype)personWithType:(PersonType)type{
        Person * p = [[Person alloc] init];
        p.type = type;
        return p;
    }
    
    - (void)eat{
        switch (self.type) {
            case PersonTypeStudent:
                NSLog(@"学生在吃饭");
                break;
            case PersonTypeTeacher:
                NSLog(@"老师在吃饭");
                break;
        }
    }
    @end
    

    使用情景代码

        Person * p = [Person personWithType:(PersonTypeTeacher)];
        [p eat]; //老师在吃饭
        
        Person * p1 = [Person personWithType:(PersonTypeStudent)];
        [p1 eat]; //学生在吃饭
    

    这样是将所有的逻辑都写在这一个类中,当类型更多的时候,比如还有农民、医生、商人、官员等等,switch分支就会越来越多,当每种类型的逻辑再复杂点,eat方法就越来越复杂。

    3.使用类族模式,Person类衍生两个子类Teacher、Student

    Person基类

    @interface Person : NSObject
    
    @property (nonatomic,copy) NSString *name;
    @property (nonatomic,copy) NSString *num;
    @property (nonatomic,assign) PersonType type;
    + (instancetype)personWithType:(PersonType)type;
    
    - (void)eat;
    
    @end
    
    @implementation Person
    
    + (instancetype)personWithType:(PersonType)type{
        switch (type) {
            case PersonTypeStudent:
                return [[Student alloc] init];
                break;
                
            case PersonTypeTeacher:
                return [[Teacher alloc] init];
                break;
        }
    }
    
    - (void)eat{
        
    }
    
    @end
    

    Student类

    @interface Student :Person
    
    @end
    @implementation Student
    
    - (void)eat{
        NSLog(@"学生在吃饭");
    }
    
    @end
    

    Teacher类

    @interface Teacher :Person
    
    @end
    @implementation Teacher
    
    -(void)eat{
        NSLog(@"老师在吃饭");
    }
    
    @end
    

    使用情景代码

        Person * p = [Person personWithType:(PersonTypeTeacher)];
        [p eat]; //老师在吃饭
        
        Person * p1 = [Person personWithType:(PersonTypeStudent)];
        [p1 eat]; //学生在吃饭
    

    可见使用时代码没有变,但是类中的逻辑被分割到子类中,当再加新的类型,就再增加新的子类就好了,基类基本无需改变,只需要在personWithType方法中增加一点判断语句就行了。逻辑更加清晰。更容易维护。
    其实这基本上就是工厂模式。Java中经常用这种模式再加上反射,有的时候personWithType这类的方法都基本无需改变。

    4.Cocoa中的类族

    Cocoa中其实有许多类族。UIButton,还有大部分的collection类都是类族。

    以NSArray为例

     NSArray *array = @[@1,@2];
     NSLog(@"%@",[array class]); //**__NSArrayI**
    

    可见array的实际类型是__NSArrayl而不是NSArray本身。

    5.判断类是否在一个类族中。

    以下代码的条件将永远无法达成

    if([array class] == [NSArray class]){
      //不会执行
    }
    
    

    类族的正确判断方式

    if([array isKindOfClass:[NSArray class]]){
      //会执行
    }
    

    6.新增Cocoa中类似NSArray这样的子类要遵守的几点规则

    • 子类应该继承自类中中的基类。
    • 子类应该定义自己的数据存储方式。
    • 子类应该复写超类文档中指明要复写的方法。(因为OC中没有抽象方法的概念)

    相关文章

      网友评论

          本文标题:(九) [OC高效系列]尽量使用类族模式来隐藏细节

          本文链接:https://www.haomeiwen.com/subject/lijesttx.html