【软件重构】软件代码坏味道之滥用switch

举报
huahua.Dr 发表于 2022/09/01 23:14:11 2022/09/01
【摘要】 switch是一种开关,是一种选择语句,用法简单,就是多分支选择语句,就是与多个if语句一样,功能上,switch与if两者可以完全可以相互取代,如果嵌套的if比较少时(三个以内),使用if比较简单,如果选择的分支比较多时,使用if会导致层数比较深,程序冗长,可读性下降;如果分支选择比较多,并且选择的类型码也比较固定的时候,可以使用switch来处理。但是如果过度使用switch,分支选择不...

switch是一种开关,是一种选择语句,用法简单,就是多分支选择语句,就是与多个if语句一样,功能上,switch与if两者可以完全可以相互取代,如果嵌套的if比较少时(三个以内),使用if比较简单,如果选择的分支比较多时,使用if会导致层数比较深,程序冗长,可读性下降;如果分支选择比较多,并且选择的类型码也比较固定的时候,可以使用switch来处理。

但是如果过度使用switch,分支选择不确定,增加或者修改一种类型码,其case分支场景就需要增加或者修改,而且会依赖case分支,不断增加场景,导致后期难以维护;那么这种情况就存在坏味道了,需要考虑重构,使用一些重构手法将switch代替掉。


常见switch坏味道有:

 1)每新增类型码时,都要增加case分支,导致分支越来越多,函数不再短小简洁,违反了开闭原则(OCP)

 2)单个case分支中多了很多事情,导致函数冗长,包含多个抽象层级,违反了单一职责原则(SRP)

 3)switch依赖类型码判断,而类型码往往通过一个统一的类来管理,如果相同的switch语句散布在多个函数中,新增类型码时,必须找出所有switch语句并修改他们,散弹式修改容易遗漏出错


不是switch坏味道的情况:

1)switch只是很简单的逻辑

2)有些设计模式必须存在switch时(如工厂设计模式)


如果解决这些switch坏味道?

1)如果是面向对象语言,可以使用多态的特性来替换它,先提取每个switch-case语句到一个函数中,再将该函数搬移到具体多态性的类中,通过子类/状态/策略取代类型码,用多态特性取代条件表达式。

2)如果面向过程语言,case分支超过5个,可以考虑使用表驱动的方式替换,如果可以预见类型码不会增加,则可以使用策略模式,将控制和处理分离,提高拓展性,符合开闭原则。


代码实现消除switch坏味道

(1)使用多态特性消除switch

public class SwitchBadCode {

    public static void main(String[] args) {

        SwitchBadCode switchBadCode =new SwitchBadCode();

        // 优化switch之前:

        switchBadCode.switchMoth("typeA");

        switchBadCode.switchMoth("typeB");

        switchBadCode.switchMoth("typeC");

        //优化之后:

        switchBadCode.switchMothAfter(new typeAImpl());

        switchBadCode.switchMothAfter(new typeBImpl());

        switchBadCode.switchMothAfter(new typeCImpl());

    }

    // switch 优化之前

    public void switchMoth(String type) {

        switch (type) {

            case "typeA":

                System.out.println("type A");

                break;

            case "typeB":

                System.out.println("type B");

                break;

            case "typeC":

                System.out.println("type C");

                break;

            default:

                System.out.println("default");


        }

    }

    // switch优化之后

    public void switchMothAfter(abstractInter abs) {

        abs.doMeth();

    }

}


/**

 * switch优化,使用多态

 * 1.抽象每个Switch 类型码 ,做成一个抽象类,抽象方法为case的执行的函数

 * 2.每个case,作为一个子类,实现抽象类,并实现其抽象方法,方法就内容就是case的内容

 * 3.使用使用子类来代替类型码,执行case的语句

 * */

interface abstractInter {

    void doMeth();

}

class typeAImpl implements abstractInter {

    @Override

    public void doMeth() {

        System.out.println("type a");

    }

}

class typeBImpl implements abstractInter {

    @Override

    public void doMeth() {

        System.out.println("type b");

    }

}

class typeCImpl implements abstractInter {

    @Override

    public void doMeth() {

        System.out.println("type c");

    }

}

(2)使用策略模式优化switch

使用策略模式也是借用多态的特性,在多态的手法上再封装一下,抽象类变成策略接口,具体实现类保持不变为业务类实现了策略,再创建一个策略类,实例化只能通过策略接口为参数的构造方法,实例化策略类之后,就可以执行策略接口定义的方法;根据不同业务实现类调用相同的方法而具备不同的行为,这就是策略模式的核心目的,同时还可以再优化一下我们如何简单的实例化策略类,可以利用工厂模式,再创建一个工厂类,只需要传递一个switch的状态码就可以实现创建不同的策略类实例,去完成不同的行为。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。