软件代码坏味道之滥用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的状态码就可以实现创建不同的策略类实例,去完成不同的行为。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值