前言
繁杂的业务代码中,总会出现各种switch
,if-else
之类的分支语句,此类语句给人的直观感觉是判断条件明确,代码层次清晰,缺点可能是代码繁琐,杂乱无章,而且拆分困难.特别是到后期维护代码的时候,这种状况往往令人有食之无味,弃之可惜的感觉.
优化方案-策略模式
策略模式百度百科:一般是指:1. 可以实现目标的方案集合;2. 根据形势发展而制定的行动方针和斗争方法;3. 有斗争艺术,能注意方式方法。
这里我们可以分析一下,每个switch或者if-else的分支无非是一块单独执行的个体,他们作为个体是为了实现某一种业务逻辑,而且是这些分支通过最后的整合回归才能完成某块特定的逻辑.
画个简单的图有助于理解:
那么这里的分支们,就完全可以看做
百科解释1
中实现目标的方案集合,也就是所谓的策略.
举个巨简单的栗子
我需要通过传入的三种类型来获取对应的id,例如id 001->类型1,id 002->类型2,id 003->类型3
下意识的代码:
if (type == 类型1) {
return 001;
}else if (type == 类型2){
return 002;
}else if (type == 类型3){
return 003;
}
那么用策略模式如何实现呢?也是一段非常简单的代码:
NSDictionary *dict =@{
@"类型1" : @001,
@"类型2" : @002,
@"类型3" : @003
};
NSInteger id = dict[type];//type 为类型1,类型2,类型3
这个dict就是一个策略的集合,我们通过type
来取出对应的结果.或许这个小例子看不出策略模式的好处,那再来一个复杂一点的例子---->>>
题目:小明在每个星期每天都会做不同的事
周一打篮球
周二逛街
周三洗衣服
周四打游戏
周五唱歌
周六看电影
周末爬山
ps:想出这些业余活动可费了不少劲.....
我们用分支来写,应该是这样的:
if(day == 周一){
result = [xiaoming playBasketball];
}else if (day == 周二){
result = [xiaoming shopping];
}else if (day == 周三){
result = [xiaoming washClothes];
}else if(...) {
...
}//很烦,写不下去了
NSLog(@"xiaoming 今天%@",result);
这里小明每天做的事,可能是一个由很复杂的逻辑组成,所以这时如果放到分支里,可能会让代码显得异常冗长难读.当然有比较牛逼的同学会说,我把逻辑抽成方法不就行了,那么每个分支里就只有调用方法的语句了
能做到这样的同学我也是由衷的佩服,但这还不够,我们这里考虑的是去除分支
.
可以这样来做:
// 1.将复杂的业务逻辑包装成invocation,这里传入的每天做的事,例如playBasketball
- (NSInvocation *)invocationWithMethod:(SEL)selector{
NSMethodSignature*signature = [CurrentClass instanceMethodSignatureForSelector:@selector(selector)];
NSInvocation*invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = @selector(selector);
return invocation;
}
// 2.将每天做的事进行整合
- (NSDictionary *)Strategies{
NSDictionary *Strategies = @{
@"day1" : [self invocationWithMethod:@selector(playBasketball)],
@"day2" : [self invocationWithMethod:@selector(shopping)],
@"day3" : [self invocationWithMethod:@selector(washClothes)],
@"day4" : [self invocationWithMethod:@selector(playGames)],
@"day5" : [self invocationWithMethod:@selector(sing)],
@"day6" : [self invocationWithMethod:@selector(watchMovie)],
@"day7" : [self invocationWithMethod:@selector(climbing)],
};
return Strategies;
}
// 3.找出小明哪天做的事
NSInvocation *doWhat = self.Strategies[whichDay];
[doWhat invoke];
通过组合策略
的方式,就能找出小明那天到底干了啥.这样就完全去除了分支代码
,并且更利于我对业务逻辑的维护和扩展,只需要对字典进行维护即可管理分支的代码.
补充:这里通过invocation包装的方式比较适合上面例子的场合,但不仅如此,我们也可以扩展到类与类,模块与模块之间的逻辑处理,脑洞大开中......
最后
或许在开发阶段,这种代码写起来可能比较耗时,因此在开发阶段,我们依然可以通过分支的方式来进行书写,到后期维护阶段,就可以选择策略模式来对代码进行重构了.
感谢abuzzworld指出上述示例代码的问题,已更正!
网友评论