首页/开发/代码质量与评审速查/坏味道:重复的 switch(Repeated Switches)
重构手法62 条

坏味道:重复的 switch(Repeated Switches)

同一组 switch 在多处按类型分支时,新增类型要改所有分支;用 Replace Conditional with Polymorphism 把分支收敛到类型体系,或先用 Extract Function 集中。

什么是重复的 switch

重复的 switch 指同一组类型分支在多个地方重复出现:新增一种类型要改所有分支,漏一处就在某条路径上出错。处方是用以多态取代条件表达式把分支收敛到类型体系,或先用提取函数把散落的分支集中到一处;如果分支少而稳定,集中在单处的判断未必比多态更差。

基本信息

典型信号同一枚举在多处分支判断,新增类型容易漏改
处方以多态取代条件表达式、提取函数
权衡分支少且稳定时,集中的判断未必更差
相邻问题发散式变化、霰弹式修改
前提类型体系能承载每种分支的行为

典型使用场景

  • 订单类型在计价、校验、通知三处各有分支判断
  • 日志级别判断散落在多个模块,规则调整要全局搜索
  • 协议版本分支写在解析与序列化两处,容易不一致
  • 权限类型在过滤与展示里各判断一次
  • 导出格式分支出现在内容生成与文件命名两处

多态化方向

多态化方向
// 把分支收敛到类型体系
interface Shipping {
    Money cost(Order order);
}
class Air implements Shipping { ... }
class Ground implements Shipping { ... }

// 调用方不再判断类型:order.shipping().cost(order)
// 新增类型只需加一个实现类

处理方式选择

情况建议理由
分支在多处重复且会扩展多态或集中一处新增类型只改一个地方
只有一处判断且分支稳定保留现状多态引入的间接层未必划算
各分支逻辑差异很大策略对象避免子类里出现互不相干的代码
迁移中最容易出错的是默认分支:多态化后原来的兜底语义往往没有对应实现,行为在边角情况下悄然改变。迁移前把默认分支的行为写成用例。
不要为两个分支就搭起类层次:抽象成本高于收益时,把判断集中到一个函数里是更经济的选择。

易错点

  • 为两个分支就引入类层次:抽象成本高于收益,代码更难读
  • 多态化后遗漏原有默认分支语义:边角行为悄然改变
  • 只把判断抽成函数却没集中:重复依然存在,只是换了个名字
  • 新增类型时没有强制失败路径:漏改分支后静默走到错误逻辑

数据来源与参考

  • 《重构》第 2 版 · 第 3 章(Repeated Switches)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌