zoukankan      html  css  js  c++  java
  • ObjectiveC中的反射和反射工厂

     本文为原创,欢迎转载和收藏,转载请标明原文地址


      程序中可能会出现大量的if-else或者switch-case来选择一系列类中的某个类进行操作,利用反射(Reflection)就可以避免这些重复判断工作。

      反射在Java中封装了类来实现,在Objective-C里面要自己来实现,好在不是很难。

      我们的目的是通过传入一个类名字符串,把字符串类名动态转化成类,并对类进行实例化和调用方法等操作。

      OC的NSRuntime中提供了将Class name转化为Class的方法"NSClassFromString()"

    NSClassFromString //方法原型
    Class NSClassFromString (
       NSString *aClassName
    );

       因此,我们就可以这样使用来动态获得一个类:

    NSString * aClassName = @"SunnyClass";
    Class class = NSClassFromString(aClassName);

      这样我们就能实例化这个类了:

    id instance = [[class alloc] init];

      如果需要使用方法,最好用reponseToSelector:来检测一下

    if([instance reponseToSelector:@selector(aMethod)])
    {
        [instance aMethod];
    }

      这样就完成了反射调用的过程。

      下面就是将反射利用到工厂模式里。

      定义一个Fruit,和三种继承自Fruit的水果

    @interface Fruit : NSObject
    - (void)show;
    @end
    
    @interface Apple : Fruit 
    @end
    
    @interface Banana : Fruit 
    @end
    
    @interface Pear : Fruit 
    @end

      实现部分,简单的show方法来打印

    @implementation Fruit
    - (void)show
    {
        NSLog(@"I'm a fruit");
    }
    @end
    
    @implementation Apple
    - (void)show
    {
        NSLog(@"I'm an apple");
    }
    @end
    
    @implementation Banana
    - (void)show
    {
        NSLog(@"I'm a banana");
    }
    @end
    
    @implementation Pear
    - (void)show
    {
        NSLog(@"I'm a pear");
    }
    @end

      如果使用传统的if-else分支判断的话,情况就会变得非常恶心,如果想再增加一个Orange类的话,不仅需要增加Orange类的代码,工厂的代码也要新增加else-if分支:

    - (Fruit *)createFruitWithName:(NSString *)fruitName
    {
        Fruit * theFruit;
        if ([fruitName isEqualToString:@"Apple"]) 
        {
            theFruit = [[[Apple alloc] init] autorelease];
        }
        else if ([fruitName isEqualToString:@"Banana"])
        {
            theFruit = [[[Banana alloc] init] autorelease];
        }
        else if ([fruitName isEqualToString:@"Pear"])
        {
            theFruit = [[[Pear alloc] init] autorelease];
        }
        return theFruit;
    }

      但如果使用反射工厂的模式,情况就变得简单了许多,扩展性也会变得更好(反射输入的类名最好能来自于一个文件,这个文件规定了哪些字符串是可以作为参数传入的,这里就不考虑了)

    @implementation FruitFactroy
    
    - (Fruit *)createFruitWithName:(NSString *)fruitName
    {
        //通过string得到类的结构体
        Class class = NSClassFromString(fruitName);
        
        //通过转化的class得到实例对象
        Fruit * theFruit = [(Fruit *)[[class alloc] init] autorelease];
        
        //调用对象方法
        if ([theFruit respondsToSelector:@selector(show)]) 
        {
            [theFruit show];
        }
        
        //返回对象
        return theFruit;
    }
    @end

      工厂方法的调用

        FruitFactroy * factroy = [[[FruitFactroy alloc] init] autorelease];
        Fruit * apple = [factroy createFruitWithName:@"Apple"];
        Fruit * banana = [factroy createFruitWithName:@"Banana"];
        Fruit * pear = [factroy createFruitWithName:@"Pear"];
  • 相关阅读:
    网页转图片,html生成图片,网页生成图片(基于linnux+phantomjs)和wkhtmltoimage
    51Nod 1031 骨牌覆盖 | Fibonacci
    51Nod 1024 矩阵中不重复的元素 | 技巧 数学
    51Nod 1014 X^2 Mod P
    51Nod 1010 只包含因子2 3 5的数 | 预处理+二分
    51Nod 1007 正整数分组 | DP (01背包)
    51Nod 1381 硬币游戏 | 概率(数学期望)
    51Nod 1347 旋转字符串 | 规律
    51Nod 1344 走格子 | 贪心
    51Nod 1305 Pairwise Sum and Divide | 思维 数学
  • 原文地址:https://www.cnblogs.com/sunnyxx/p/2473146.html
Copyright © 2011-2022 走看看