【软件重构】软件代码坏味道之滥用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的状态码就可以实现创建不同的策略类实例,去完成不同的行为。
- 点赞
- 收藏
- 关注作者
评论(0)