概述
使用 if - else 的兩種常見場景:
// 1.非空異常判斷
id object;
if (object == nil) {
// code
} else {
// code
}
// 2.值狀態(tài)判斷
if ([object isMemberOfClass:[NSObject class]]) {
// code
} else {
// code
}
對于第一種情況,可采取的優(yōu)化方式有
- 合并條件表達(dá)式
- 減少嵌套
- 移除臨時變量等
原則是盡可能地維持正常流程代碼在最外層腾啥,異常判斷最先判斷猪狈。
對于第二種情況
- 可以將每個狀態(tài)對應(yīng)的代碼段封裝成一個方法晰赞,這樣代碼可以更清晰
- 使用多態(tài)替代 if - else 代碼段
值得注意的是括儒,對于第一種使用 if-else 的情況,可以多多優(yōu)化罢洲,但對于第二種情況踢故,要慎重使用,不能為了優(yōu)化而優(yōu)化惹苗。
非空異常判斷 if - else 代碼段的優(yōu)化
1.合并表達(dá)式殿较,使代碼更清晰易懂
int number = 100;
// 優(yōu)化前
if (number > 10) {
return nil;
}
if (number < -10) {
return nil;
}
if (number == 5) {
return nil;
}
// 使用合并表達(dá)式條件優(yōu)化后
if (number > 10 || number < -10 || number == 5) {
return nil;
}
2.減少 if - else 嵌套,將包含關(guān)系改為平行關(guān)系桩蓉,避免邏輯嵌套太深淋纲,使代碼邏輯清晰明了,一目了然院究。
int money = 6;
// 優(yōu)化前
if (money < 0) {
return @"食不果腹洽瞬,衣不蔽體";
} else if (money > 100) {
return @"財(cái)務(wù)自由";
} else if (money > 10) {
return @"小康家庭";
} else if (money > 5) {
return @"溫飽不愁";
} else {
return @"貧困家庭";
}
// 優(yōu)化后
if (money < 0) {
return @"食不果腹,衣不蔽體";
}
if (money > 100) {
return @"財(cái)務(wù)自由";
}
if (money > 10) {
return @"小康家庭";
}
if (money > 5) {
return @"溫飽不愁";
}
return @"貧困家庭";
3.將異常判斷放在最前面业汰,且盡量減少臨時變量改用return直接返回伙窃,使代碼邏輯清晰。
int number = 10;
BOOL flag = NO;
BOOL otherFlag = NO;
// 優(yōu)化前
if (number > 10) {
return nil;
}
if (otherFlag) {
int result = 0;
if (flag) {
result = number * 2;
} else {
result = number *-2;
}
return result;
}
return nil;
// 將上面的異常判斷放在最前面样漆,且較少臨時變量的使用, 再合并表達(dá)式且將判斷改為平行關(guān)系为障。異常條件先退出這一條可適用于請求網(wǎng)絡(luò)數(shù)據(jù)后,對網(wǎng)絡(luò)數(shù)據(jù)進(jìn)行判斷格式檢查時,先將異常情況的處理放在最前面鳍怨。
if (number > 10 && !otherFlag) {
return nil;
}
if (flag) {
return number * 2;
}
return number *-2;
值狀態(tài) if-else 的優(yōu)化
1.將每種狀態(tài)下的長段代碼提取成一個函數(shù)
int number = 10;
// 優(yōu)化前
if (number > 10) {
// code balabala...
} else {
// code balabala...
}
// 優(yōu)化前
if (number > 10) {
[self funationA];
} else {
[self funationB];
}
2.使用多態(tài)替代 if-else
以上闡述其他的優(yōu)化方式只能優(yōu)化 if-else 代碼段結(jié)構(gòu)呻右,但使用多態(tài)可以替代 if-else 。
這里使用多態(tài) + map + 反射具體實(shí)現(xiàn)鞋喇,當(dāng)然還有其他幾種實(shí)現(xiàn)方式,比如策略模式 + 工廠模式声滥,不過我認(rèn)為這種實(shí)現(xiàn)方式過于龐大。
舉例來說侦香,現(xiàn)在有個業(yè)務(wù)需求:根據(jù)汽車品牌落塑,獲取汽車配置。
使用 if-else 實(shí)現(xiàn)需求
NSString *carBrand = @"BMW";
if ([carBrand isEqualToString:@"BMW"]) {
// BMW Configuration
} else if ([carBrand isEqualToString:@"Benz"]) {
// Benz Configuration
}
使用多態(tài) + map + 反射實(shí)現(xiàn)
//1. 聲明汽車抽象類
@interface Car : NSObject
// 這個方法也可以提取到一個protocol中
- (NSString *)configuration;
@end
//2. 聲明具體的汽車子類罐韩,并實(shí)現(xiàn)其相應(yīng)方法
//2.1 聲明 BenzCar 類
@interface BenzCar : Car
@end
@implementation BenzCar
- (NSString *)configuration {
return @"BenzCar configuration";
}
@end
//2.2 聲明 BMWCar 類
@interface BMWCar : Car
@end
@implementation BMWCar
- (NSString *)configuration {
return @"BMWCar configuration";
}
@end
//3. 實(shí)現(xiàn)使用map + 反射機(jī)制的依托類
// 3.1 類的聲明
@interface CarConfigurationHelper : NSObject
+ (NSString *)carConfigurationWithCarBrand:(NSString *)brand;
@end
// 3.2 類的實(shí)現(xiàn)
@implementation CarConfigurationHelper
+ (NSString *)carConfigurationWithCarBrand:(NSString *)brand {
static NSDictionary *map = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
map = @{
@"Benz" : [BenzCar class],
@"BMW" : [BMWCar class]
};
});
if (!map[brand]) {
return nil;
}
Car *car = [[map[brand] alloc] init];
return [car configuration];
}
@end
//4.客戶端的使用
- (void)function {
NSString *configuration = [CarConfigurationHelper carConfigurationWithCarBrand:@"BMW"];
NSLog(@"Car configuration: %@",configuration);
}
參考:《重構(gòu)_改善既有代碼的設(shè)計(jì)》