引言:何为好代码?
在软件工程领域,重构被比作"整理代码的房间"。好的代码不仅要能工作,还应具备可读性、可维护性和可扩展性。让我们从一个真实案例开始,探索重构的艺术。
第一部分:重构前的"烂代码"分析
1.1 典型烂代码特征
让我们先看一个电商系统中订单处理的典型烂代码:
java
// 重构前:违反几乎所有设计原则的代码 public class OrderProcessor { public void processOrder(String orderId, String customerType, boolean isDiscount, double discountRate, boolean isGiftWrap, boolean isExpressShipping) { // 1. 验证订单 if (orderId == null || orderId.isEmpty()) { System.out.println("订单ID无效"); return; } // 2. 计算价格 double basePrice = getBasePrice(orderId); double finalPrice = basePrice; if (isDiscount) { finalPrice = basePrice * (1 - discountRate); } // 3. 处理礼品包装 if (isGiftWrap) { finalPrice += 10.0; System.out.println("添加礼品包装"); // 发送包装通知 sendGiftWrapNotification(orderId); } // 4. 处理快递运输 if (isExpressShipping) { finalPrice += 25.0; System.out.println("添加快递运输"); // 更新库存 updateInventoryForExpress(orderId); } // 5. 保存订单 saveOrderToDatabase(orderId, finalPrice); // 6. 发送通知 if (customerType.equals("VIP")) { sendVIPNotification(orderId); } else if (customerType.equals("Regular")) { sendRegularNotification(orderId); } else if (customerType.equals("New")) { sendNewCustomerNotification(orderId); } // 7. 生成报告 generateReport(orderId, "daily"); // 8. 更新用户积分 updateCustomerPoints(orderId, customerType); System.out.println("订单处理完成"); } // 数十个辅助方法混杂在一起... private double getBasePrice(String orderId) { /* 实现 */ } private void saveOrderToDatabase(String orderId, double price) { /* 实现 */ } private void sendGiftWrapNotification(String orderId) { /* 实现 */ } private void updateInventoryForExpress(String orderId) { /* 实现 */ } // ... 更多方法 }1.2 代码问题诊断
违反单一职责原则:一个方法做太多事情
违反开闭原则:添加新功能需要修改现有代码
长方法反模式:方法过长,难以理解和维护
条件语句滥用:if-else链难以扩展
紧耦合:业务逻辑与通知、数据库操作紧密耦合
第二部分:重构策略与设计模式应用
2.1 第一步:应用单一职责原则
java
// 重构第一步:职责分离 public class OrderValidator { public boolean validateOrder(String orderId) { return orderId != null && !orderId.isEmpty(); } } public class PriceCalculator { public double calculatePrice(String orderId, DiscountStrategy discountStrategy, List<OrderDecorator> decorators) { double basePrice = getBasePrice(orderId); double price = discountStrategy.applyDiscount(basePrice); for (OrderDecorator decorator : decorators) { price = decorator.decorate(price); } return price; } } public class NotificationService { public void sendNotification(String orderId, CustomerType customerType) { NotificationStrategy strategy = NotificationFactory.createStrategy(customerType); strategy.send(orderId); } }2.2 第二步:应用策略模式处理折扣
java
// 策略模式:封装变化的折扣算法 public interface DiscountStrategy { double applyDiscount(double price); } public class NoDiscountStrategy implements DiscountStrategy { @Override public double applyDiscount(double price) { return price; } } public class PercentageDiscountStrategy implements DiscountStrategy { private double percentage; public PercentageDiscountStrategy(double percentage) { this.percentage = percentage; } @Override public double applyDiscount(double price) { return price * (1 - percentage); } } public class FixedAmountDiscountStrategy implements DiscountStrategy { private double amount; public FixedAmountDiscountStrategy(double amount) { this.amount = amount; } @Override public double applyDiscount(double price) { return Math.max(0, price - amount); } } // 使用策略模式的折扣计算器 public class DiscountCalculator { private DiscountStrategy strategy; public void setStrategy(DiscountStrategy strategy) { this.strategy = strategy; } public double calculateDiscountedPrice(double originalPrice) { return strategy.applyDiscount(originalPrice); } }2.3 第三步:应用装饰者模式处理订单附加服务
java
// 装饰者模式:动态添加订单功能 public interface OrderComponent { double getCost(); String getDescription(); } public class BasicOrder implements OrderComponent { private double basePrice; public BasicOrder(double basePrice) { this.basePrice = basePrice; } @Override public double getCost() { return basePrice; } @Override public String getDescription() { return "基础订单"; } } public abstract class OrderDecorator implements OrderComponent { protected OrderComponent decoratedOrder; public OrderDecorator(OrderComponent decoratedOrder) { this.decoratedOrder = decoratedOrder; } @Override public double getCost() { return decoratedOrder.getCost(); } @Override public String getDescription() { return decoratedOrder.getDescription(); } } public class GiftWrapDecorator extends OrderDecorator { public GiftWrapDecorator(OrderComponent decoratedOrder) { super(decoratedOrder); } @Override public double getCost() { return super.getCost() + 10.0; } @Override public String getDescription() { return super.getDescription() + ", 礼品包装"; } } public class ExpressShippingDecorator extends OrderDecorator { public ExpressShippingDecorator(OrderComponent decoratedOrder) { super(decoratedOrder); } @Override public double getCost() { return super.getCost() + 25.0; } @Override public String getDescription() { return super.getDescription() + ", 快递运输"; } }2.4 第四步:应用观察者模式实现事件通知
java
// 观察者模式:订单状态变更通知 public interface OrderObserver { void update(OrderEvent event); } public interface OrderSubject { void registerObserver(OrderObserver observer); void removeObserver(OrderObserver observer); void notifyObservers(); } public class Order implements OrderSubject { private String orderId; private OrderStatus status; private List<OrderObserver> observers = new ArrayList<>(); @Override public void registerObserver(OrderObserver observer) { observers.add(observer); } @Override public void removeObserver(OrderObserver observer) { observers.remove(observer); } @Override public void notifyObservers() { OrderEvent event = new OrderEvent(this.orderId, this.status); for (OrderObserver observer : observers) { observer.update(event); } } public void setStatus(OrderStatus status) { this.status = status; notifyObservers(); } } // 具体观察者 public class EmailNotificationObserver implements OrderObserver { @Override public void update(OrderEvent event) { System.out.println("发送邮件通知: 订单 " + event.getOrderId() + " 状态变更为 " + event.getStatus()); } } public class InventoryUpdateObserver implements OrderObserver { @Override public void update(OrderEvent event) { if (event.getStatus() == OrderStatus.SHIPPED) { System.out.println("更新库存: 订单 " + event.getOrderId() + " 已发货"); } } }2.5 第五步:应用工厂模式创建对象
java
// 工厂模式:封装对象创建逻辑 public interface OrderFactory { Order createOrder(String orderId, Customer customer); } public class RegularOrderFactory implements OrderFactory { @Override public Order createOrder(String orderId, Customer customer) { Order order = new Order(); order.setOrderId(orderId); order.setCustomer(customer); order.setType(OrderType.REGULAR); return order; } } public class VIPOrderFactory implements OrderFactory { @Override public Order createOrder(String orderId, Customer customer) { Order order = new Order(); order.setOrderId(orderId); order.setCustomer(customer); order.setType(OrderType.VIP); order.setPriority(true); return order; } } public class OrderFactoryProvider { public static OrderFactory getFactory(CustomerType customerType) { switch (customerType) { case VIP: return new VIPOrderFactory(); case REGULAR: return new RegularOrderFactory(); default: throw new IllegalArgumentException("未知的客户类型"); } } }第三部分:重构后的完整代码结构
java
// 重构后的主处理器 public class OrderProcessor { private OrderValidator validator; private PriceCalculator priceCalculator; private NotificationService notificationService; private OrderRepository orderRepository; public OrderProcessor() { this.validator = new OrderValidator(); this.priceCalculator = new PriceCalculator(); this.notificationService = new NotificationService(); this.orderRepository = new OrderRepository(); } public void processOrder(OrderRequest request) { // 1. 验证 if (!validator.validateOrder(request.getOrderId())) { throw new IllegalArgumentException("订单无效"); } // 2. 创建订单对象 OrderFactory factory = OrderFactoryProvider.getFactory(request.getCustomerType()); Order order = factory.createOrder(request.getOrderId(), request.getCustomer()); // 3. 计算价格 DiscountStrategy discountStrategy = createDiscountStrategy(request); List<OrderDecorator> decorators = createDecorators(request); double finalPrice = priceCalculator.calculatePrice( request.getOrderId(), discountStrategy, decorators ); order.setTotalPrice(finalPrice); // 4. 保存订单 orderRepository.save(order); // 5. 注册观察者 registerObservers(order); // 6. 状态变更触发通知 order.setStatus(OrderStatus.PROCESSING); // 7. 发送特定通知 notificationService.sendNotification(request.getOrderId(), request.getCustomerType()); } private DiscountStrategy createDiscountStrategy(OrderRequest request) { if (request.getDiscountType() == DiscountType.PERCENTAGE) { return new PercentageDiscountStrategy(request.getDiscountValue()); } else if (request.getDiscountType() == DiscountType.FIXED_AMOUNT) { return new FixedAmountDiscountStrategy(request.getDiscountValue()); } return new NoDiscountStrategy(); } private List<OrderDecorator> createDecorators(OrderRequest request) { List<OrderDecorator> decorators = new ArrayList<>(); OrderComponent basicOrder = new BasicOrder(getBasePrice(request.getOrderId())); if (request.isGiftWrap()) { decorators.add(new GiftWrapDecorator(basicOrder)); } if (request.isExpressShipping()) { decorators.add(new ExpressShippingDecorator(basicOrder)); } return decorators; } private void registerObservers(Order order) { order.registerObserver(new EmailNotificationObserver()); order.registerObserver(new InventoryUpdateObserver()); order.registerObserver(new ReportGenerationObserver()); } }第四部分:重构前后对比分析
4.1 可维护性对比
| 维度 | 重构前 | 重构后 |
|---|---|---|
| 方法长度 | 80+行 | 10-20行 |
| 类职责 | 8+个职责 | 单一职责 |
| 修改影响 | 牵一发而动全身 | 局部影响 |
| 测试难度 | 难以单元测试 | 易于测试 |
4.2 扩展性对比
假设需要添加新的折扣类型:
重构前:
java
// 需要修改processOrder方法,添加新的if条件 if (discountType.equals("SEASONAL")) { // 添加新逻辑 }重构后:
java
// 只需添加新策略类 public class SeasonalDiscountStrategy implements DiscountStrategy { @Override public double applyDiscount(double price) { // 实现季节性折扣 } }4.3 代码复用性
重构后各组件可独立复用:
DiscountStrategy可用于任何需要折扣的场景OrderDecorator可用于任何需要添加额外服务的场景OrderObserver可用于任何需要事件通知的场景
第五部分:重构最佳实践与注意事项
5.1 重构的时机
三次法则:第三次做类似事情时进行重构
添加功能时:在添加新功能前改进代码结构
修复Bug时:理解代码时顺便重构
代码审查时:审查他人代码时提出重构建议
5.2 重构的安全网
java
// 1. 编写测试覆盖 @Test public void testOrderProcessing() { OrderProcessor processor = new OrderProcessor(); OrderRequest request = createTestRequest(); processor.processOrder(request); // 验证结果 assertOrderSaved(request.getOrderId()); assertNotificationSent(request.getCustomerType()); } // 2. 小步前进,频繁测试 public class RefactoringSession { public void safeRefactor() { // 步骤1: 提取方法 extractMethod(); runTests(); // 步骤2: 移动方法 moveMethodToProperClass(); runTests(); // 步骤3: 引入设计模式 introduceStrategyPattern(); runTests(); } } // 3. 版本控制提交策略 // 每次重构步骤后立即提交,便于回滚5.3 常见重构手法速查表
| 重构手法 | 适用场景 | 设计模式结合 |
|---|---|---|
| 提取方法 | 长方法,重复代码 | 策略模式基础 |
| 提取类 | 大类,多职责 | 单一职责原则 |
| 移动方法 | 方法放在错误类 | 工厂模式准备 |
| 替换条件语句 | 复杂switch/if链 | 策略/状态模式 |
| 引入参数对象 | 过长参数列表 | 建造者模式 |
第六部分:设计模式选择指南
6.1 根据问题选择模式
| 问题类型 | 推荐模式 | 示例 |
|---|---|---|
| 算法变化 | 策略模式 | 折扣计算 |
| 对象创建复杂 | 工厂/建造者 | 订单创建 |
| 状态变化通知 | 观察者 | 订单状态更新 |
| 动态添加功能 | 装饰者 | 订单附加服务 |
| 复杂对象结构 | 组合模式 | 购物车 |
| 简化接口 | 外观模式 | 支付系统 |
6.2 模式组合使用示例
java
// 组合使用多个设计模式 public class EnhancedOrderProcessor { // 外观模式:简化复杂子系统调用 public ProcessingResult processEnhancedOrder(EnhancedOrderRequest request) { // 建造者模式:构建复杂对象 Order order = new OrderBuilder() .withId(request.getId()) .withCustomer(request.getCustomer()) .withItems(request.getItems()) .build(); // 策略模式:算法选择 PaymentStrategy paymentStrategy = PaymentStrategyFactory .createStrategy(request.getPaymentMethod()); // 装饰者模式:动态添加功能 OrderComponent decoratedOrder = new BasicOrder(order); if (request.isInsured()) { decoratedOrder = new InsuranceDecorator(decoratedOrder); } // 模板方法模式:固定流程 return processWithTemplate(order, paymentStrategy); } // 模板方法模式:定义算法骨架 protected ProcessingResult processWithTemplate(Order order, PaymentStrategy strategy) { validate(order); double amount = calculateAmount(order); boolean paid = strategy.pay(amount); if (paid) { return confirmOrder(order); } return failOrder(order); } }第七部分:重构的度量与评估
7.1 代码质量指标
java
// 重构前后的量化对比 public class CodeQualityMetrics { // 圈复杂度:从重构前的15+降低到3-5 public static int calculateCyclomaticComplexity(MethodNode method) { // 实现圈复杂度计算 } // 代码行数:减少30%-50% public static int countLinesOfCode(File javaFile) { // 统计代码行数 } // 类耦合度:降低依赖关系 public static int calculateCoupling(ClassNode clazz) { // 计算耦合度 } // 内聚性:提高相关功能的集中度 public static double calculateCohesion(ClassNode clazz) { // 计算内聚性 } }7.2 业务价值指标
缺陷率:重构后缺陷减少40%
开发速度:新功能开发时间缩短30%
** onboarding时间**:新成员理解代码时间从2周减少到3天
部署频率:由于测试更容易,部署频率提高
第八部分:总结与建议
8.1 重构的核心原则
渐进式改进:小步快跑,持续改进
测试驱动:无测试,不重构
保持功能:重构不改变外部行为
适时停止:达到"足够好"即可
8.2 从新手到专家的路径
text
初级阶段:学习重构手法 ↓ 中级阶段:识别代码坏味道 ↓ 高级阶段:预设计模式应用 ↓ 专家阶段:架构级重构
8.3 工具推荐
IDE重构工具:IntelliJ IDEA、Eclipse的重构功能
静态分析工具:SonarQube、Checkstyle
测试工具:JUnit、Mockito
版本控制:Git(便于回滚)
8.4 最后建议
"重构不是一次性的活动,而是一种持续实践。优秀的代码不是一开始就设计出来的,而是在不断重构中演化出来的。"
记住:最好的重构时机是现在。从小处开始,从最痛的代码开始,逐步培养重构习惯。每一次重构都是对代码质量的投资,最终将带来可维护性、可扩展性和开发效率的显著提升。