重构手法——函数行为重塑类 | 语意 | 用查询替换参数

55 阅读2分钟

简介

"用查询替换参数"是简化方法接口的重要重构手法。通过将参数计算逻辑移至方法内部,可以减少参数传递层级,提高方法的内聚性并降低调用复杂度。

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

  • 方法参数可从其他参数推导得出
  • 参数值依赖对象内部状态
  • 多个方法使用相同参数计算逻辑
  • 参数传递导致调用链过长

用查询替换参数的详细步骤

  1. 识别候选参数
    • 查找可被其他参数推导的参数
    • 确认参数值的确定性来源
  2. 提取参数计算逻辑
    • 将参数计算封装为查询方法
    • 确保计算逻辑无副作用
  3. 修改方法签名
    • 移除目标参数声明
    • 更新方法内部引用
  4. 重构调用方
    • 移除调用处的参数传递
    • 保持原有业务逻辑不变

示例

重构前代码:

class OrderService {
    double getDiscountedPrice(Order order, boolean isVIP) {
        double basePrice = order.getAmount();
        return isVIP ? basePrice * 0.9 : basePrice;
    }

    void applyDiscount(Order order, boolean isVIP) {
        double finalPrice = getDiscountedPrice(order, isVIP);
        order.setFinalPrice(finalPrice);
    }
}

重构步骤:

  1. 将isVIP参数改为内部查询:

    class OrderService {
        double getDiscountedPrice(Order order) {
            double basePrice = order.getAmount();
            return isVIP(order) ? basePrice * 0.9 : basePrice;
        }
    
        private boolean isVIP(Order order) {
            return order.getCustomer().isVIP();
        }
    
        void applyDiscount(Order order) {
            double finalPrice = getDiscountedPrice(order);
            order.setFinalPrice(finalPrice);
        }
    }
    

练习

基础练习题

  1. 简单参数替换

    // 重构前
    class Calculator {
        double circleArea(double radius, double pi) {
            return pi * radius * radius;
        }
    }
    

进阶练习题

  1. 对象状态参数替换

    // 重构前
    class Employee {
        void applyRaise(double performanceScore, double salary) {
            if (performanceScore > 0.8) {
                salary *= 1.1;
            }
            this.salary = salary;
        }
    }
    

综合拓展练习题

  1. 多参数替换

    // 重构前
    class ShippingService {
        double calculateCost(double weight, double size, boolean isInternational) {
            double base = weight * size;
            return isInternational ? base * 1.3 : base;
        }
    }
    

代码审查要点

  1. 优点:

    • 简化方法调用接口
    • 集中核心计算逻辑
    • 减少参数传递错误
  2. 潜在问题:

    • 确保查询方法幂等性
    • 避免引入隐藏依赖
    • 注意计算性能影响