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

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

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

TargetExecutor executor = ExecutorFactory.getExecutor(target);
executor.process();

这是工厂类的代码

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来保存键值对,

private static HashMap<String, TargetExecutor> mMappings = new HashMap<>();

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

public abstract String matchUri();

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

//处理target.startsWith("#RANGE")的情况
public class ExecutorWithTag extends TargetExecutor {
    public void process() {
        ....
    }

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

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

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嵌套了, 下面是摘完之后的工厂类的代码,

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里, 这样各个模块之前的耦合就能降的很低,大家也就只需要关注自己的功能就行。

原文发布于微信公众号 - Android每日一讲(gh_f053f29083b9)

原文发表时间:2018-06-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

第九节 Go语言循环语句

干货来了!!!为了让更多的小伙伴喜欢Golang、加入Golang之中来,Golang语言社区发起人彬哥联合业界大牛共同推出了Go语言基础、进阶、提高课程,目前...

842
来自专栏AzMark

Python列表与元组

1353
来自专栏程序员互动联盟

【编程基础】main函数,你知道多少?

近期学习时对这个问题产生了迷惑,看到了这篇文章,感觉挺好。 在C/C++的学习过程中,一个很常见的问题就是void main和int main有什么区别呢?本文...

3568
来自专栏怀英的自我修炼

Java漫谈8

今天我们来聊聊字符串。 字符串,在Java中一个最接近与8大数据类型的存在。甚至于由于它太好用了,以至于在编写代码的时候都快忘了有个叫char的基本数据类型了。...

35610
来自专栏MyBlog

Effective.Java 读书笔记(10)关于toString

针对于java.lang.Object已经帮我们实现好了的toString方法,当我们自己定义出来的类使用这古老的toString方法的时候,通常不会返回给你一...

1374
来自专栏向治洪

Scala入门

Scala入门 Scala简介 ps:在最新的薪资调查中,Scala程序员的工资是平均最高的Scala工资。 Scala是一门多范式的编程语言,一种类似java...

1997
来自专栏程序员宝库

关于 Java 你不知道的 10 件事

作为 Java 书呆子,比起实用技能,我们会对介绍 Java 和 JVM 的概念细节更感兴趣。因此我想推荐 Lukas Eder 在 jooq.org 发表的原...

3776
来自专栏程序员宝库

关于 Java 你不知道的 10 件事

作为 Java 书呆子,比起实用技能,我们会对介绍 Java 和 JVM 的概念细节更感兴趣。因此我想推荐 Lukas Eder 在 jooq.org 发表的原...

3005
来自专栏一个会写诗的程序员的博客

《Kotin 极简教程》第7章 面向对象编程(OOP)(1)第7章 面向对象编程(OOP)《Kotlin极简教程》正式上架:

在前面的章节中,我们学习了Kotlin的语言基础知识、类型系统、集合类以及泛型相关的知识。在本章节以及下一章中,我们将一起来学习Kotlin对面向对象编程以及函...

952
来自专栏青玉伏案

PHP精选数组函数

编程怎么能少的了数组呢,以下是学习PHP时常用的数组处理函数。在编程中要遵循一个原则就是DRY(Don`t Repeat Yourself)原则,PHP中有大...

2248

扫码关注云+社区

领取腾讯云代金券