Java方法封装优化案例
原始版本 - 未优化的长方法
public class OrderService {
public void processOrder(Order order) {
// 验证订单
if (order == null) {
throw new IllegalArgumentException("订单不能为空");
}
if (order.getItems() == null || order.getItems().isEmpty()) {
throw new IllegalArgumentException("订单项不能为空");
}
if (order.getTotalAmount() <= 0) {
throw new IllegalArgumentException("订单金额必须大于0");
}
// 计算折扣
double discount = 0;
if (order.getTotalAmount() > 1000) {
discount = 0.1;
} else if (order.getTotalAmount() > 500) {
discount = 0.05;
}
double finalAmount = order.getTotalAmount() * (1 - discount);
// 更新库存
for (OrderItem item : order.getItems()) {
Product product = productRepository.findById(item.getProductId());
if (product.getStock() < item.getQuantity()) {
throw new RuntimeException("库存不足: " + product.getName());
}
product.setStock(product.getStock() - item.getQuantity());
productRepository.save(product);
}
// 发送通知
String message = String.format("订单 %s 已处理,金额: %.2f",
order.getOrderId(), finalAmount);
notificationService.send(order.getUserId(), message);
// 保存订单
order.setStatus("PROCESSED");
orderRepository.save(order);
}
}
优化版本 - 单一职责原则
@Service
public class OrderService {
private final OrderValidator orderValidator;
private final DiscountCalculator discountCalculator;
private final InventoryManager inventoryManager;
private final NotificationService notificationService;
private final OrderRepository orderRepository;
public OrderService(OrderValidator orderValidator,
DiscountCalculator discountCalculator,
InventoryManager inventoryManager,
NotificationService notificationService,
OrderRepository orderRepository) {
this.orderValidator = orderValidator;
this.discountCalculator = discountCalculator;
this.inventoryManager = inventoryManager;
this.notificationService = notificationService;
this.orderRepository = orderRepository;
}
public void processOrder(Order order) {
// 1. 校验订单
orderValidator.validate(order);
// 2. 计算折扣和最终金额
double finalAmount = discountCalculator.calculateFinalAmount(order);
// 3. 更新库存
inventoryManager.updateStock(order.getItems());
// 4. 发送通知
notificationService.sendOrderProcessedNotification(order, finalAmount);
// 5. 保存订单
saveProcessedOrder(order, finalAmount);
}
private void saveProcessedOrder(Order order, double finalAmount) {
order.setFinalAmount(finalAmount);
order.setStatus("PROCESSED");
orderRepository.save(order);
}
}
各个职责分离的类
// 订单校验器
@Component
public class OrderValidator {
public void validate(Order order) {
validateNotNull(order);
validateItems(order.getItems());
validateTotalAmount(order.getTotalAmount());
}
private void validateNotNull(Order order) {
if (order == null) {
throw new IllegalArgumentException("订单不能为空");
}
}
private void validateItems(List<OrderItem> items) {
if (items == null || items.isEmpty()) {
throw new IllegalArgumentException("订单项不能为空");
}
// 可以继续验证每个商品
items.forEach(this::validateItem);
}
private void validateItem(OrderItem item) {
if (item.getQuantity() <= 0) {
throw new IllegalArgumentException("商品数量必须大于0");
}
}
private void validateTotalAmount(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("订单金额必须大于0");
}
}
}
// 折扣计算器
@Component
public class DiscountCalculator {
private static final double HIGH_DISCOUNT_THRESHOLD = 1000;
private static final double MID_DISCOUNT_THRESHOLD = 500;
private static final double HIGH_DISCOUNT_RATE = 0.1;
private static final double MID_DISCOUNT_RATE = 0.05;
public double calculateFinalAmount(Order order) {
double discount = getDiscountRate(order.getTotalAmount());
return order.getTotalAmount() * (1 - discount);
}
private double getDiscountRate(double totalAmount) {
if (totalAmount > HIGH_DISCOUNT_THRESHOLD) {
return HIGH_DISCOUNT_RATE;
}
if (totalAmount > MID_DISCOUNT_THRESHOLD) {
return MID_DISCOUNT_RATE;
}
return 0;
}
}
// 库存管理器
@Component
public class InventoryManager {
private final ProductRepository productRepository;
public InventoryManager(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public void updateStock(List<OrderItem> items) {
items.forEach(this::updateSingleItemStock);
}
private void updateSingleItemStock(OrderItem item) {
Product product = findProduct(item.getProductId());
validateStock(product, item.getQuantity());
product.setStock(product.getStock() - item.getQuantity());
productRepository.save(product);
}
private Product findProduct(String productId) {
return productRepository.findById(productId)
.orElseThrow(() -> new RuntimeException("商品不存在: " + productId));
}
private void validateStock(Product product, int requiredQuantity) {
if (product.getStock() < requiredQuantity) {
throw new RuntimeException("库存不足: " + product.getName());
}
}
}
// 通知服务
@Component
public class NotificationService {
public void sendOrderProcessedNotification(Order order, double finalAmount) {
String message = buildNotificationMessage(order, finalAmount);
sendNotification(order.getUserId(), message);
}
private String buildNotificationMessage(Order order, double finalAmount) {
return String.format("订单 %s 已处理,金额: %.2f",
order.getOrderId(), finalAmount);
}
private void sendNotification(String userId, String message) {
// 实际发送逻辑
System.out.println("发送通知给用户 " + userId + ": " + message);
}
}
策略模式优化折扣计算
// 折扣策略接口
public interface DiscountStrategy {
double calculateDiscount(double totalAmount);
boolean supports(double totalAmount);
}
// 高级折扣策略
@Component
public class HighDiscountStrategy implements DiscountStrategy {
private static final double THRESHOLD = 1000;
private static final double DISCOUNT_RATE = 0.1;
@Override
public double calculateDiscount(double totalAmount) {
return totalAmount * DISCOUNT_RATE;
}
@Override
public boolean supports(double totalAmount) {
return totalAmount > THRESHOLD;
}
}
// 中级折扣策略
@Component
public class MidDiscountStrategy implements DiscountStrategy {
private static final double THRESHOLD = 500;
private static final double DISCOUNT_RATE = 0.05;
@Override
public double calculateDiscount(double totalAmount) {
return totalAmount * DISCOUNT_RATE;
}
@Override
public boolean supports(double totalAmount) {
return totalAmount > THRESHOLD && totalAmount <= 1000;
}
}
// 优化后的折扣计算器
@Component
public class AdvancedDiscountCalculator {
private final List<DiscountStrategy> strategies;
public AdvancedDiscountCalculator(List<DiscountStrategy> strategies) {
this.strategies = strategies;
}
public double calculateFinalAmount(Order order) {
double totalAmount = order.getTotalAmount();
double discount = findApplicableStrategy(totalAmount)
.map(strategy -> strategy.calculateDiscount(totalAmount))
.orElse(0.0);
return totalAmount - discount;
}
private Optional<DiscountStrategy> findApplicableStrategy(double totalAmount) {
return strategies.stream()
.filter(strategy -> strategy.supports(totalAmount))
.findFirst();
}
}
单元测试示例
@SpringBootTest
class OrderServiceTest {
@MockBean
private OrderValidator orderValidator;
@MockBean
private DiscountCalculator discountCalculator;
@MockBean
private InventoryManager inventoryManager;
@MockBean
private NotificationService notificationService;
@MockBean
private OrderRepository orderRepository;
@Autowired
private OrderService orderService;
@Test
void testProcessOrder() {
// 准备测试数据
Order order = createTestOrder();
// 设置mock行为
Mockito.doNothing().when(orderValidator).validate(any(Order.class));
Mockito.when(discountCalculator.calculateFinalAmount(any(Order.class)))
.thenReturn(1000.0);
Mockito.doNothing().when(inventoryManager).updateStock(anyList());
Mockito.doNothing().when(notificationService)
.sendOrderProcessedNotification(any(Order.class), anyDouble());
// 执行测试
orderService.processOrder(order);
// 验证
Mockito.verify(orderRepository).save(any(Order.class));
assertEquals("PROCESSED", order.getStatus());
assertEquals(1000.0, order.getFinalAmount(), 0.01);
}
}
优化总结
| 优化前 | 优化后 | 优点 |
|---|---|---|
| 单个长方法 | 多个职责分离的类 | 可维护性提高 |
| 硬编码业务逻辑 | 策略模式 | 易于扩展新折扣规则 |
| 直接依赖具体实现 | 依赖注入 | 便于测试和替换 |
| 无单元测试 | 完善的单元测试 | 保证代码质量 |
| 魔法数值 | 常量定义 | 代码更清晰 |
这种优化方式遵循了SOLID原则,特别是单一职责原则和开闭原则,使代码更加健壮、可测试和可维护。
