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

  • 相关阅读:
    Android BottomSheet总结
    Chrome:如何在页面树状显示后端返回的JSON数据
    Redis源码学习(31),字典学习,dict.c(一)
    Linux 程序编译过程详解
    QT学习day1
    EasyPoi导入校验+导入自定义查询等校验
    Java进公司首先要做的准备工作-maven、idea、Tomcat安装和配置
    linux 网络命令
    rk3568 Android 11在系统怎样执行命令获取SN号
    125. 验证回文串 【简单题】
  • 原文地址:https://blog.csdn.net/use_admin/article/details/126552337