Objective-C中的反射和反射工廠


 本文為原創,歡迎轉載和收藏,轉載請標明原文地址


 

  程序中可能會出現大量的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"];

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM