美文网首页
[iOS]使用策略模式来去除繁琐的if-else

[iOS]使用策略模式来去除繁琐的if-else

作者: 未来行者 | 来源:发表于2017-11-29 00:03 被阅读507次

    前言

    繁杂的业务代码中,总会出现各种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指出上述示例代码的问题,已更正!

    相关文章

      网友评论

          本文标题:[iOS]使用策略模式来去除繁琐的if-else

          本文链接:https://www.haomeiwen.com/subject/zfdybxtx.html