Java案例如何实现代码重构?

wen python案例 5

Java代码重构的实现方法

代码重构是改善既有代码设计而不改变其外部行为的过程,以下是具体的实现方法和案例:

Java案例如何实现代码重构?

重构的基本原则

  1. 小步修改:每次只做小的改动
  2. 测试保障:重构前必须有充分的测试
  3. 不改变功能:保持外部行为不变

常见重构案例及实现

提取方法(Extract Method)

重构前

public void printOwing(String name) {
    double outstanding = 0.0;
    // 打印标题
    System.out.println("*************************");
    System.out.println("***** Customer Owes *****");
    System.out.println("*************************");
    // 计算欠款
    Enumeration e = orders.elements();
    while (e.hasMoreElements()) {
        Order each = (Order) e.nextElement();
        outstanding += each.getAmount();
    }
    // 打印详细信息
    System.out.println("name: " + name);
    System.out.println("amount: " + outstanding);
}

重构后

public void printOwing(String name) {
    printBanner();
    double outstanding = getOutstanding();
    printDetails(name, outstanding);
}
private void printBanner() {
    System.out.println("*************************");
    System.out.println("***** Customer Owes *****");
    System.out.println("*************************");
}
private double getOutstanding() {
    double result = 0.0;
    Enumeration e = orders.elements();
    while (e.hasMoreElements()) {
        Order each = (Order) e.nextElement();
        result += each.getAmount();
    }
    return result;
}
private void printDetails(String name, double outstanding) {
    System.out.println("name: " + name);
    System.out.println("amount: " + outstanding);
}

提取类(Extract Class)

重构前

public class Person {
    private String name;
    private String officeAreaCode;
    private String officeNumber;
    public String getTelephoneNumber() {
        return "(" + officeAreaCode + ") " + officeNumber;
    }
    // getter/setter...
}

重构后

public class Person {
    private String name;
    private TelephoneNumber officeTelephone = new TelephoneNumber();
    public String getTelephoneNumber() {
        return officeTelephone.getTelephoneNumber();
    }
    // getter/setter...
}
public class TelephoneNumber {
    private String areaCode;
    private String number;
    public String getTelephoneNumber() {
        return "(" + areaCode + ") " + number;
    }
    // getter/setter...
}

用多态替代条件表达式

重构前

public double getSpeed() {
    switch (_type) {
        case EUROPEAN:
            return getBaseSpeed();
        case AFRICAN:
            return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;
        case NORWEGIAN_BLUE:
            return (_isNailed) ? 0 : getBaseSpeed(_voltage);
    }
    throw new RuntimeException("Should be unreachable");
}

重构后

abstract class Bird {
    abstract double getSpeed();
}
class EuropeanSwallow extends Bird {
    double getSpeed() {
        return getBaseSpeed();
    }
}
class AfricanSwallow extends Bird {
    double getSpeed() {
        return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;
    }
}
class NorwegianBlueParrot extends Bird {
    double getSpeed() {
        return (_isNailed) ? 0 : getBaseSpeed(_voltage);
    }
}

引入参数对象(Introduce Parameter Object)

重构前

public void addDateRange(Date start, Date end) {
    // ...
}
public boolean isInRange(Date start, Date end, Date date) {
    // ...
}

重构后

public class DateRange {
    private final Date start;
    private final Date end;
    public DateRange(Date start, Date end) {
        this.start = start;
        this.end = end;
    }
    public boolean contains(Date date) {
        return !date.before(start) && !date.after(end);
    }
}
public void addDateRange(DateRange range) {
    // ...
}
public boolean isInRange(DateRange range, Date date) {
    return range.contains(date);
}

重构工具的使用

IDE内置重构功能

  • IntelliJ IDEA:Ctrl+Alt+Shift+T(重构菜单)
  • Eclipse:Alt+Shift+T(重构菜单)
  • NetBeans:Ctrl+Shift+R(重构)

常用重构快捷操作

// 重命名类/方法/变量
// Shift+F6 (IntelliJ) / Alt+Shift+R (Eclipse)
// 提取方法
// Ctrl+Alt+M (IntelliJ) / Alt+Shift+M (Eclipse)
// 内联变量
// Ctrl+Alt+N (IntelliJ)
// 移动成员
// F6 (IntelliJ) 

重构策略和步骤

重构流程

graph TD
    A[识别坏味道] --> B[编写测试]
    B --> C[小步重构]
    C --> D[运行测试]
    D --> E{测试通过?}
    E -->|是| F[提交代码]
    E -->|否| G[回退修改]
    G --> C
    F --> H[继续下一个重构?]
    H -->|是| A
    H -->|否| I[结束]

代码坏味道识别清单

  • 过长方法(Long Method)
  • 过大类(Large Class)
  • 重复代码(Duplicated Code)
  • 过长参数列表(Long Parameter List)
  • 发散式变化(Divergent Change)
  • 霰弹式修改(Shotgun Surgery)
  • 依恋情结(Feature Envy)

实际项目重构案例

电商订单处理系统重构

重构前(存在重复代码和过长方法):

public class OrderService {
    public void processOrder(Order order) {
        // 验证订单
        if (order.getItems().isEmpty()) {
            throw new IllegalArgumentException("Order has no items");
        }
        if (order.getCustomer() == null) {
            throw new IllegalArgumentException("No customer");
        }
        if (!order.getCustomer().isValid()) {
            throw new IllegalArgumentException("Customer invalid");
        }
        // 计算总额
        double total = 0;
        for (Item item : order.getItems()) {
            total += item.getPrice() * item.getQuantity();
            // 应用折扣
            if (item.getCategory() == Category.ELECTRONICS) {
                total *= 0.9;
            } else if (item.getCategory() == Category.BOOKS) {
                total *= 0.95;
            }
        }
        // 发送邮件
        EmailService.sendOrderConfirmation(order.getCustomer().getEmail(), 
            order.getId(), total);
    }
}

重构后

public class OrderService {
    private final OrderValidator validator;
    private final PriceCalculator priceCalculator;
    private final NotificationService notificationService;
    public OrderService() {
        this.validator = new OrderValidator();
        this.priceCalculator = new PriceCalculator();
        this.notificationService = new EmailNotificationService();
    }
    public void processOrder(Order order) {
        validator.validate(order);
        double total = priceCalculator.calculateTotal(order);
        notificationService.sendOrderConfirmation(order, total);
    }
}
public class OrderValidator {
    public void validate(Order order) {
        validateItems(order);
        validateCustomer(order.getCustomer());
    }
    private void validateItems(Order order) {
        if (order.getItems().isEmpty()) {
            throw new IllegalArgumentException("Order has no items");
        }
    }
    private void validateCustomer(Customer customer) {
        if (customer == null) {
            throw new IllegalArgumentException("No customer");
        }
        if (!customer.isValid()) {
            throw new IllegalArgumentException("Customer invalid");
        }
    }
}
public class PriceCalculator {
    public double calculateTotal(Order order) {
        double total = 0;
        for (Item item : order.getItems()) {
            total += calculateItemPrice(item);
        }
        return total;
    }
    private double calculateItemPrice(Item item) {
        double price = item.getPrice() * item.getQuantity();
        return applyDiscount(price, item.getCategory());
    }
    private double applyDiscount(double price, Category category) {
        DiscountStrategy strategy = DiscountStrategyFactory.getStrategy(category);
        return strategy.applyDiscount(price);
    }
}

重构最佳实践

  1. 测试驱动重构:先写测试,再重构
  2. 持续集成:频繁提交,避免大规模改动
  3. 代码审查:团队协作进行重构审查
  4. 文档更新:重构后更新相关文档
  5. 性能考虑:避免过度重构影响性能

通过以上方法,可以系统化地进行Java代码重构,提升代码质量和可维护性。

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