前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >重构 - 完全不用 if-else 可能吗?

重构 - 完全不用 if-else 可能吗?

作者头像
PhoenixZheng
发布2018-08-07 16:17:39
5170
发布2018-08-07 16:17:39
举报

上次那篇重构-为什么 if-else 不是好代码 说到代码中的 if-else会随着代码量的增加,在迭代的过程中变的越来越难以维护, 然后用工厂模式的思路可以把 if-else代码块给剥离开来, 不过有朋友提出了不足, 虽然表面上看没有 if-else了,但其实只是给挪到工厂里面去。 这不是换汤不换药嘛?

但其实想完全不用 if-else也是可能的,还是以上次那段代码为例子来说, 这是最终在调用端的代码

代码语言:javascript
复制
TargetExecutor executor = ExecutorFactory.getExecutor(target);
executor.process();

这是工厂类的代码

代码语言:javascript
复制
public class ExecutorFactory {
    public TargetExecutor getExecutor(String target) {
      if (target.startsWith("#RANGE")) {
        return new ExecutorWithTag();
      } else if (target.contains("#RANGE")) {
        ....
      } else if (target.startsWith("#")) {
        ....
      } else if (target.contains("#")) {
        ....
      } else {
        ....
      }
    }
}
开始重构

我们关注的重点是 getExecutor()这个方法,这里一堆 if-else, 可以看到这里面的逻辑是根据 target 字符串的不同内容实例化不同的 executor对象给调用者使用, 也就是说,这里是一种多对多的模式,对于这种模式我们可以考虑用一个 HashMap来保存键值对,

代码语言:javascript
复制
private static HashMap<String, TargetExecutor> mMappings = new HashMap<>();

而判断 target内容的逻辑也不需要放在工厂类里了,可以重构 TargetExecutor的代码,给它增加一个抽象方法,

代码语言:javascript
复制
public abstract String matchUri();

这个方法的作用就是返回需要跟它匹配的字符串, 比如 ExecutorWithTag,那么它返回的是 "RANGE", 如果是 ExecutorWithStash,那么它返回的是 "#". 我们把新增的代码列出来,

代码语言:javascript
复制
//处理target.startsWith("#RANGE")的情况
public class ExecutorWithTag extends TargetExecutor {
    public void process() {
        ....
    }

    public String matchUri(){
     return "RANGE";
    }
}

准备工作好,还记得我们实例化了一个 HashMap吗,以String和Executor作为键值对的, 现在我们需要另外一个方法来把 executor放到 HashMap里,

代码语言:javascript
复制
private static void addExecutor(RouterExeBase executor) {
    mMappings.put(executor.matchUri(), executor);
}

static {
    addExecutor(new ExecutorWithTag());
    addExecutor(new ExecutorWithStash());
    ....
}
完全摘除 if-else

在准备工作做到这里后,我们就需要来把工厂中的 if-else摘除了, 我们把之前的条件判断改成了从一个 map 中遍历查找匹配的模式,虽然从逻辑上来说,遍历查找跟 if-else差不多, 但代码会变更简洁,也不会再看到一长串的 if-else嵌套了, 下面是摘完之后的工厂类的代码,

代码语言:javascript
复制
public class ExecutorFactory {
    public TargetExecutor getExecutor(String target) {
      for(String pattern : mMappings.keySet()) {
          if(target.contains(pattern)) {
             return mMappings.get(pattern);
          }
      }
    }
}

这只是一种代码中的小技巧,可以在重构代码的时候让整个代码逻辑清晰很多, 但是也有弊端, 因为需要通过 pattern 去查找匹配,就会有可能出现 pattern 类似或者重叠的情况,一不小心就会导致bug... 对于这种情况上面的重构方法就没那么好了, 所以我习惯的话会把 if-else 剥离到工厂中就结束,但如果涉及到多个模块的人之间的合作的话, 才会再拆分一层,让大家自己把自己的 executor 在静态方法块中注册到 mMapping里, 这样各个模块之前的耦合就能降的很低,大家也就只需要关注自己的功能就行。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开始重构
  • 完全摘除 if-else
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档