重构手法——函数行为重塑类 | 语意 | 用子类替换类型代码

27 阅读2分钟

简介

"用子类替换类型代码"是实现多态行为的关键重构手法。通过将类型标识符转换为子类层次,可以消除条件判断逻辑,提高代码的可扩展性和可维护性。

针对的症状(代码坏味道)

  • 使用枚举或字符串表示对象类型
  • 存在基于类型代码的条件分支
  • 需要为不同类型添加差异化行为
  • 类型代码影响对象创建方式

用子类替换类型代码的详细步骤

  1. 识别类型代码
    • 查找表示类型的字段
    • 标记相关条件逻辑
  2. 创建子类层次
    • 为每个类型代码创建子类
    • 使用工厂方法封装创建逻辑
  3. 迁移类型行为
    • 将条件逻辑移至子类
    • 使用多态替代类型判断
  4. 移除类型字段
    • 删除原始类型代码字段
    • 调整类型相关方法

示例

重构前代码:

class Employee {
    static final int ENGINEER = 0;
    static final int MANAGER = 1;

    private int type;

    Employee(int type) {
        this.type = type;
    }

    double getBonus() {
        return type == ENGINEER ? 1000 : 2000;
    }
}

重构步骤:

  1. 创建抽象子类:

    abstract class Employee {
        abstract double getBonus();
    
        static Employee create(int type) {
            return switch (type) {
                case ENGINEER -> new Engineer();
                case MANAGER -> new Manager();
                default -> throw new IllegalArgumentException();
            };
        }
    }
    
  2. 实现具体子类:

    class Engineer extends Employee {
        double getBonus() {
            return 1000;
        }
    }
    
    class Manager extends Employee {
        double getBonus() {
            return 2000;
        }
    }
    

练习

基础练习题

  1. 简单类型子类化

    // 重构前
    class Product {
        static final int BOOK = 0;
        private int type;
    }
    

进阶练习题

  1. 复杂行为迁移

    // 重构前
    class Order {
        private String status; // "NEW", "PAID"
    
        boolean canCancel() {
            return "NEW".equals(status);
        }
    }
    

综合拓展练习题

  1. 多类型系统

    // 重构前
    class Vehicle {
        static final int CAR = 0;
        static final int TRUCK = 1;
    
        double calculateTax() {
            return this.type == CAR ? 0.1 : 0.2;
        }
    }
    

代码审查要点

  1. 优点:

    • 消除条件判断逻辑
    • 支持开闭原则
    • 提高代码可读性
  2. 潜在问题:

    • 控制子类数量
    • 保持工厂方法简洁
    • 注意类型系统扩展成本