优化if-else结构
if-else是日常使用较多的语法结构,但是正确使用if-else却并不是一件简单的事情,需要保证所有的逻辑都被包括且处理逻辑不会出现重叠,在一定程度上会导致设计复杂,代码的可读性差,并且可能会导致重构困难。
- 场景一: if-else 过多
if (A) {
...
....
} else if (B) {
....
....
} else if (C) {
....
....
} else if(D) {
....
....
} else {
....
....
}
缺点:代码处理逻辑会越来越多,可维护性变差.
- 场景二: if-else 嵌套过深
if (condition1) {
action1();
if (condition2) {
action2();
if (condition3) {
action3();
if (condition4) {
action4();
}
}
}
}
缺点: 可读性差,难以维护,一看就懵.
事实上,对于else结构更应该关注的是不同场景下的实现,而不是如果进行场景划分。在很多if-else结构中,并不需要将所有的场景都进行列举,只需要将需要单独处理的场景进行特殊处理即可.这样就可以尝试将日常if-else结构进行优化.
去除完全不必要的else模块
在一些场景中,多个场景之间没有公用逻辑,else的使用完全不必要,添加else反而会使得代码显得冗余. 例如:
// 完全没有必要
- (NSString *)performOperation:(NSInteger)input {
if (input > 0) {
return @"available";
} else {
return @"unavailable";
}
}
// 基本没有必要
- (void)performOperation:(NSInteger)input {
if (input > 0) {
// do something
} else {
// do some other things
}
}
这时else的出现完全没有必要,可以直接将else移除
- (NSString *)performOperation:(NSInteger)input {
if (input > 0) return @"available";
return @"unavailable";
}
- (void)performOperation:(NSInteger)input {
if (input > 0) {
// do something
return;
}
// do some other things
}
这样实现看起来就会清爽很多,所以如果if中已经出现了return就可以尝试将其后出现的else去掉.
价值分配
当需要根据输入进行变量赋值操作时,停止使用if-else废话,使用更具可读性的方法。
-(NSString *)getLevel:(CGFloat)score {
NSString *level = @"";
if (score > 90) {
level = @"A";
} else if (score > 80) {
level = "B";
} else if (score > 60) {
level = @"C";
} else {
level = @"D"
}
retuen level;
}
在这个实现里不仅if-else结构显得多余,局部变量其实也没有什么实际的意义,都可以优化掉:
-(NSString *)getLevel:(CGFloat)score {
if (score > 90) return @"A";
if (score > 80) return "B";
if (score > 60) return @"C";
return @"D"
}
与之前的else相比,及时使用return进行终止的优势在于:
- 可以终止当前场景下的代码执行,阅读时只需要看到当前场景下的return就可以确定该场景下的功能已经结束,不用担心后续还有其他操作;
- 一般来讲及时使用return终止替换else可以使代码更加简洁,减少书写量.
提前语句检查
在一些方法中,如果参数提供了无效的值,继续执行实现将毫无意义.例如:
-(NSString *)getGender:(NSInteger)input {
if (input == 0) {
return @"Man";
} else if (input == 1) {
return @"Woman";
} else {
return @"UnKnown";
}
}
对于这种情况就可以提前进行输入性检查,如果提供了无效的参数值,就终止执行:
-(NSString *)getGender:(NSInteger)input {
if (input != 0 && input != 1) return @"UnKnown";
return input == 0 ? @"Man" : @"Woman";
}
将if-else转化为字典结构
如果需要根据输入条件进行一些选择性操作,未来可能会添加更多的操作:
-(void)performOperation:(NSString *)type {
if ([type isEqualToString: "location"]) {
// get location
} else if ([type isEqualToString: "encript"]){
// do encript
} else {
// others
}
}
这种设计方式在需要添加的新的处理时,需要在后续添加更多的else操作,不方便阅读且会显得很冗长。这时候就可以将其转化为字典进行维护:
-(void)performOperation:(NSString *)type {
NSMutableDictionary<NSString *, void(^)(void)> *operations = @{}.mutableCopy;
operations[@"location"] = ^{/* get location */};
operations[@"encript"] = ^{/* do encript*/ };
// if you need to add extra operation, add here
if (operations.keys.indexOf(type) == NSNotfound) return;
operations[type]();
}
扩展应用程序
通过自定义对象使用更高级的抽象模式来消除if-else结构。例如:
-(NSString *)printOrder:(Order *)order formatType:(NSString *)formatType {
NSString *result = @"";
if ([format isEqualToString: @"JSON"]) {
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:order options:0 error:&error];
if (jsonData && !error) {
result = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
} else if([format isEqualToString: @"PlainText"] {
result = [NSString stringWithFormat: @"id: %@, sum: %@", order.id, order.sum];
} else {
result = @"Unkonown format";
}
return result;
}
这种处理看起来很凌乱所有的不同处理都放在一个逻辑里。
@interface Strateg : NSObject
+ (instanceType)strategyWithFormatType:(NSString *)formatType;
- (NSString *)converOrderToString: (Order *)order;
@end
@implementation Strategy
+(instanceType)strategyWithFormatType:(NSString *)formatType {
NSString *classStr = [NSString stringWithFormat: @"%@Strategy", formatType];
Class class = NSClassFromString(classStr);
return [[class alloc] init];
}
-(NSString *)converOrderToString {
return @"Unknown format";
}
@end
@interface JSONStrategy : Strategy
@end
@implementation
- (NSString *)converOrderToString:(Order *)order {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:order options:0 error:&error];
if (!jsonData && !error) {
NSString *result = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
return result;
}
return [super converOrderToString: order];
}
@end
@interface PlainTextStrategy : Strategy
@end
@implementation
- (NSString *)converOrderToString:(Order *)order {
return [NSString stringWithFormat: @"id: %@, sum: %@", order.id, order.sum];
}
@end
这样代码就会变成这样,是不是优美一点了?
-(NSString *)printOrder:(Order *)order formatType:(NSString *)formatType {
NSString *result = [Stragety strategyWithFormatType:formatType];
return result;
}