重构条件语句案例

wen java案例 3

本文目录导读:

重构条件语句案例

  1. 案例一:卫语句取代嵌套条件(最经典)
  2. 案例二:条件表达式分解为函数
  3. 案例三:以多态取代条件(策略模式)
  4. 案例四:合并重复的条件片段
  5. 案例五:用对象代替开关(任务分发)
  6. 重构决策速查表

我将为你展示几个典型的条件语句重构案例,从坏味道好设计的完整对比。

卫语句取代嵌套条件(最经典)

❌ 原代码:深嵌套金字塔

public double getPayAmount() {
    double result;
    if (isDead) {
        result = deadAmount();
    } else {
        if (isSeparated) {
            result = separatedAmount();
        } else {
            if (isRetired) {
                result = retiredAmount();
            } else {
                result = normalPayAmount();
            }
        }
    }
    return result;
}

✅ 重构后:卫语句提前返回

public double getPayAmount() {
    if (isDead) return deadAmount();
    if (isSeparated) return separatedAmount();
    if (isRetired) return retiredAmount();
    return normalPayAmount();
}

效果:嵌套从3层降为0层,逻辑主干一目了然。


条件表达式分解为函数

❌ 原代码:判断逻辑隐藏在一行大布尔表达式里

public double calculateDiscount(Order order, Customer customer) {
    if (order.getTotal() > 1000 
        && customer.getLoyaltyYears() > 2 
        && customer.isVIP() 
        && !order.deliveryIsUrgent()) {
        return order.getTotal() * 0.2;
    }
    return order.getTotal() * 0.05;
}

✅ 重构后:提取描述性函数

public double calculateDiscount(Order order, Customer customer) {
    if (isEligibleForBigDiscount(order, customer)) {
        return order.getTotal() * 0.2;
    }
    return order.getTotal() * 0.05;
}
private boolean isEligibleForBigDiscount(Order order, Customer customer) {
    return order.getTotal() > 1000 
        && customer.hasLoyaltyYears(2) 
        && customer.isVIP() 
        && !order.deliveryIsUrgent();
}

以多态取代条件(策略模式)

❌ 原代码:switch 不断增长(违反开闭原则)

public class AnimalSound {
    public void makeSound(String animalType) {
        switch (animalType) {
            case "Dog":
                System.out.println("Woof");
                break;
            case "Cat":
                System.out.println("Meow");
                break;
            case "Cow":
                System.out.println("Moo");
                break;
            // 每新增一种动物,都要改这里
            default:
                throw new IllegalArgumentException("Unknown animal");
        }
    }
}

✅ 重构后:策略 + 工厂

public interface Animal {
    void makeSound();
}
public class Dog implements Animal {
    public void makeSound() { System.out.println("Woof"); }
}
public class Cat implements Animal {
    public void makeSound() { System.out.println("Meow"); }
}
public class Cow implements Animal {
    public void makeSound() { System.out.println("Moo"); }
}
public class SoundPlayer {
    private Map<String, Animal> animalMap = new HashMap<>();
    public void playSound(String type) {
        Animal animal = animalMap.get(type);
        if (animal != null) {
            animal.makeSound();
        } else {
            throw new IllegalArgumentException("Unknown animal");
        }
    }
}

效果:新增动物时无需改动已有代码,只需新增类并注册到 Map。


合并重复的条件片段

❌ 原代码:相同代码在不同分支重复

public void process(Order order) {
    if (order.isExpress()) {
        System.out.println("计算运费...");
        double fee = order.getWeight() * 3.5;
        System.out.println("快速订单费用: " + fee);
        sendConfirmation(order, "EXPRESS");
        notifyWarehouse(order);
    } else {
        System.out.println("计算运费...");
        double fee = order.getWeight() * 1.2;
        System.out.println("普通订单费用: " + fee);
        sendConfirmation(order, "NORMAL");
        notifyWarehouse(order);
    }
}

✅ 重构后:提取公共部分到末尾

public void process(Order order) {
    double fee;
    if (order.isExpress()) {
        fee = order.getWeight() * 3.5;
        System.out.println("快速订单费用: " + fee);
        sendConfirmation(order, "EXPRESS");
    } else {
        fee = order.getWeight() * 1.2;
        System.out.println("普通订单费用: " + fee);
        sendConfirmation(order, "NORMAL");
    }
    // 公共部分提取到分支外
    notifyWarehouse(order);
}

用对象代替开关(任务分发)

❌ 原代码:命令字符串判断

public void executeTask(String command, Context context) {
    if (command.equals("send_email")) {
        // 发送邮件逻辑(20行)
        context.sendEmail(context.getUser().getEmail(), "Welcome!");
    } else if (command.equals("generate_report")) {
        // 生成报告逻辑(30行)
        ReportGenerator.generate(context.getData());
    } else if (command.equals("update_database")) {
        // 更新数据库逻辑(15行)
        DatabaseManager.update(context.getData());
    }
    // 20 个 if-else...
}

✅ 重构后:Command Pattern(命令模式)

public interface Command {
    void execute(Context context);
}
public class SendEmailCommand implements Command {
    public void execute(Context context) {
        context.sendEmail(context.getUser().getEmail(), "Welcome!");
    }
}
public class GenerateReportCommand implements Command {
    public void execute(Context context) {
        ReportGenerator.generate(context.getData());
    }
}
public class UpdateDatabaseCommand implements Command {
    public void execute(Context context) {
        DatabaseManager.update(context.getData());
    }
}
// 注册表
public class CommandRegistry {
    private Map<String, Command> commands = new HashMap<>();
    public CommandRegistry() {
        commands.put("send_email", new SendEmailCommand());
        commands.put("generate_report", new GenerateReportCommand());
        commands.put("update_database", new UpdateDatabaseCommand());
    }
    public void execute(String command, Context context) {
        Command cmd = commands.getOrDefault(command, 
            ctx -> { throw new UnsupportedOperationException(command); });
        cmd.execute(context);
    }
}

重构决策速查表

代码气味 重构手法 适用场景
嵌套过深 (3层+) 卫语句 有大量提前返回机会
复杂布尔表达式 提取函数 条件可命名描述
switch/if-else 频繁变化 多态/策略 分支类型稳定且明确
分支内重复代码 合并片段 重复代码不在分支逻辑中
命令字符串匹配 命令模式 有大量相似操作

核心原则

  • 代码可读性 > 代码行数(短不一定好)
  • 意图表达 > 执行细节(名字比注释更重要)
  • 开闭原则:对扩展开放,对修改封闭

如果你想看某个具体类型的重构(如金额计算、权限判断、状态流转),告诉我,我可以针对具体业务场景再给出示例。

抱歉,评论功能暂时关闭!