用Objective-C中的替代构造替换大量if语句的方法

时间:2011-11-09 17:32:15

标签: objective-c

我有一个相当冗长的if语句。 if语句检查字符串“type”以确定应该实例化的对象类型。这是一个样本......

if ( [type rangeOfString:@"coin-large"].location != NSNotFound ) 
{
   ... create large coin ...
   mgr = gameLayer.coinLargeMgr;
}
else if ( [type rangeOfString:@"coin-small"].location != NSNotFound ) 
{
   mgr = gameLayer.coinLargeMgr;
}

... more else statements ...

myObject = [mgr getNewObject];

“else-if”语句继续用于其他对象类型,这些对象类型现在约为20,并且该数字可能会增加。这很有效,但在维护和效率方面,我认为可以改进。我现在的主要候选人是创建一个NSDictionary键入对象类型字符串(coin-small,coin-large等)以及应该绑定到该类型的manager对象的值。我的想法是,这将是我需要创建的对象类型的快速查找。不确定这是最好的方法,继续看其他选项,但很好奇这里的人们可能为类似的问题做了什么。非常感谢任何帮助/反馈。

2 个答案:

答案 0 :(得分:6)

您可以使用填充了ObjC'Blocks'的NSDictionary来执行类似开关的语句,该语句执行所需的代码。因此,创建一个字典,将字符串键映射到一个代码块,以便在找到每个代码时执行:

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
                      ^{ NSLog(@"found key1"); }, @"key1", 
                      ^{ NSLog(@"found key2"); }, @"key2", 
                      nil];

你可能只是在早期阶段就像在构造函数或静态初始化程序中准备这个字典一样,以便在你的后续代码执行时准备就绪。

然后代替你的if / else块,从你收到的任何输入中切出字符串键(或者你可能不需要切片,无论如何):

NSString *input = ...
NSRange range = ...
NSString *key = [input substringWithRange:range]; 

执行(快速)字典查找以执行代码。然后执行:

void (^myBlock)(void) = [dict objectForKey:key];
myBlock();

答案 1 :(得分:5)

字典方法很容易实现。假设在创建字典时各种管理器已经归结为特定的实例,它几乎与任何面向对象的语言相同:

NSDictionary *stringsToManagers = 
    [NSDictionary dictionaryWithObjectsAndKeys:
         @"coin-large", gameLayer.coinLargeMgr,
         @"coin-small", gameLayer.coinSmallMgr,
         nil];

// this is assuming that type may contain multiple types; otherwise
// just use [stringsToManagers objectForKey:string]
for(NSString *string in [stringsToManagers allKeys])
{
    if([type rangeOfString:string].location != NSNotFound)
    {
         [[stringsToManagers objectForKey:string] addNewObject];
         // or get it and store it wherever it should go
    }
}

如果所有管理人员都提供适当的对象,那么面向对象的方法可能就越多:

NSDictionary *stringsToClasses = 
    [NSDictionary dictionaryWithObjectsAndKeys:
         @"coin-large", [LargeCoin class],
         @"coin-small", [SmallCoin class],
         nil];

// this is assuming that type may contain multiple types; otherwise
// just use [stringsToManagers objectForKey:string]
for(NSString *string in [stringsToManagers allKeys])
{
    if([type rangeOfString:string].location != NSNotFound)
    {
         id class = [stringsToManagers objectForKey:string];

         id newObject = [[class alloc] init];
         // this is exactly the same as if, for example, you'd
         // called [[LargeCoin alloc] init] after detecting coin-large
         // within the input string; you should obviously do something
         // with newObject now
    }
}

如果你的程序结构合适,这可以节省你必须编写任何经理。