Service子私有方法过多导致屎山的解决思路

Service层主方法业务逻辑过长

当我们的业务逻辑过长是,我们就需要提供子方法,供主方法进行调用。

主方法可以当做一个流程调用,具体的实现逻辑都放在对应的子方法中

在抽象子方法的时候我们通常有以下几种方式:

1.提取私有方法,紧跟住方法后面

当我们的业务逻辑不是很复杂,抽出来的私有子方法不是很多是,就可以放在住方法的后面跟随。

要求子方法数量控制在1~3个最为合适

scss 复制代码
@Service
public class OrderService {

    // 主方法
    public OrderResult createOrder(CreateOrderRequest request) {
        // 检查库存
        checkInventory(request);
        // 构建订单
        Order order = buildOrder(request, price);
        // 保存订单
        return saveOrder(order);
    }
    
    // 私有方法
    private void checkInventory(CreateOrderRequest request) { }
    private Order buildOrder(CreateOrderRequest request, BigDecimal price) { }
    private OrderResult saveOrder(Order order) { }
}

2.提取Handler类

如果子私有方法过多就不适合跟主方法写在一起了。我们可以选择创建Handler类,用于处理那些可以复用的业务逻辑,然后主方法去调用。

选择Helper类的情况:

  • 私有方法过多,4~6个
  • 私有方法逻辑相对复杂(每个10+行)
  • 功能相对独立(如价格计算、库存检查)
  • 可能在其他Service中复用
  • 便于单独测试

原来的Service(有点臃肿):

scss 复制代码
@Service
public class OrderService {
    
    public OrderResult createOrder(CreateOrderRequest request) {
        // 校验请求参数
        validateOrderRequest(request);
        // 计算价格
        BigDecimal price = calculateOrderPrice(request);
        // 检查库存
        checkInventory(request);
        // 构建订单
        Order order = buildOrder(request, price);
        // 保存订单
        return saveOrder(order);
    }
    
    // 5个私有方法,让Service变得有点长
    private void validateOrderRequest(CreateOrderRequest request) { }
    private BigDecimal calculateOrderPrice(CreateOrderRequest request) { }
    private void checkInventory(CreateOrderRequest request) { }
    private Order buildOrder(CreateOrderRequest request, BigDecimal price) { }
    private OrderResult saveOrder(Order order) { }
}

重构后(提取Helper类):

提取价格计算Helper:

scss 复制代码
@Component
public class OrderPriceHelper {
    
    public BigDecimal calculatePrice(CreateOrderRequest request) {
        BigDecimal basePrice = getBasePrice(request);
        BigDecimal discountPrice = applyDiscount(basePrice, request);
        return addTax(discountPrice);
    }
    
    private BigDecimal getBasePrice(CreateOrderRequest request) { }
    private BigDecimal applyDiscount(BigDecimal basePrice, CreateOrderRequest request) { }
    private BigDecimal addTax(BigDecimal price) { }
}

提取库存检查Helper:

typescript 复制代码
@Component
public class OrderInventoryHelper {
    
    public void checkInventory(CreateOrderRequest request) {
        for (OrderItem item : request.getItems()) {
            validateItemStock(item);
            reserveStock(item);
        }
    }
    
    private void validateItemStock(OrderItem item) { }
    private void reserveStock(OrderItem item) { }
}

简化后的Service:

scss 复制代码
@Service
public class OrderService {
    
    @Resource
    private OrderPriceHelper orderPriceHelper;
    
    @Resource  
    private OrderInventoryHelper orderInventoryHelper;
    
    public OrderResult createOrder(CreateOrderRequest request) {
        validateOrderRequest(request);
        
        BigDecimal price = orderPriceHelper.calculatePrice(request);
        orderInventoryHelper.checkInventory(request);
        
        Order order = buildOrder(request, price);
        return saveOrder(order);
    }
    
    // 只保留核心的2个私有方法
    private Order buildOrder(CreateOrderRequest request, BigDecimal price) { }
    private OrderResult saveOrder(Order order) { }
}

3.提取Processor类

如果主方法的子私有方法超过5~6个,且复用率很低或基本无法复用,就可以创建一个Processor类封装相应业务逻辑。然后service层的业务类调用Processor类的入口即可。

scss 复制代码
// 订单处理器 - 专门处理订单创建的完整流程
@Component
public class OrderCreationProcessor {
    
    // 处理完整的订单创建流程,只被OrderService使用
    public OrderResult process(CreateOrderRequest request) {
        // 完整的业务流程:校验 -> 计算 -> 库存 -> 构建 -> 保存 -> 通知
        validateRequest(request);
        PriceInfo price = calculateTotalPrice(request);
        InventoryInfo inventory = reserveInventory(request);
        Order order = buildOrder(request, price, inventory);
        OrderResult result = saveOrder(order);
        sendNotifications(result);
        return result;
    }
    
    // 大量私有方法,只为这个流程服务
    private void validateRequest(...) { /* 20行代码 */ }
    private PriceInfo calculateTotalPrice(...) { /* 30行代码 */ }
    private InventoryInfo reserveInventory(...) { /* 25行代码 */ }
    private Order buildOrder(...) { /* 40行代码 */ }
    private OrderResult saveOrder(...) { /* 15行代码 */ }
    private void sendNotifications(...) { /* 20行代码 */ }
}

// 只被一个Service使用
@Service
public class OrderService {
    @Resource
    private OrderCreationProcessor orderProcessor; // 专用
    
    public OrderResult createOrder(CreateOrderRequest request) {
        return orderProcessor.process(request);
    }
}

4.Handler和Processor类的区别

特征 Helper类 Processor类
职责范围 辅助功能,工具性质 完整业务流程
复杂度 相对简单,单一职责 复杂,多步骤协调
复用性 高复用,多处调用 低复用,专用处理
方法数量 1-3个公共方法 1个主process方法 + 大量私有方法
业务 完整性 处理业务片段 处理完整流程

5.Handler类和Utils类的区别

特征 Helper类 Utils类
Spring管理 ✅ @Component,可注入依赖 ❌ 纯静态类,无Spring依赖
方法类型 实例方法 静态方法
依赖注 可以@Resource其他Bean 不能注入,无状态
业务逻辑 可以包含业务逻辑 纯工具方法,无业务逻辑
数据访问 可以访问数据库/调用服务 不能访问外部资源

🔧 Helper类 - 业务辅助,可注入依赖:

scss 复制代码
// 业务辅助类,有依赖注入
@Component
public class OrderPriceHelper {
    
    @Resource
    private DiscountService discountService;  // 需要注入其他服务
    
    @Resource
    private TaxConfigRepository taxConfigRepository;  // 需要访问数据库
    
    // 实例方法,包含业务逻辑
    public BigDecimal calculatePrice(List<OrderItem> items, Long userId) {
        BigDecimal basePrice = calculateBasePrice(items);
        
        // 调用其他服务获取用户折扣 - 业务逻辑
        DiscountInfo discount = discountService.getUserDiscount(userId);
        BigDecimal discountedPrice = applyDiscount(basePrice, discount);
        
        // 访问数据库获取税率配置 - 业务逻辑
        TaxConfig taxConfig = taxConfigRepository.findByRegion("CN");
        return addTax(discountedPrice, taxConfig.getRate());
    }
    
    private BigDecimal calculateBasePrice(List<OrderItem> items) { }
    private BigDecimal applyDiscount(BigDecimal price, DiscountInfo discount) { }
    private BigDecimal addTax(BigDecimal price, BigDecimal taxRate) { }
}

// 使用方式:需要注入
@Service
public class OrderService {
    @Resource
    private OrderPriceHelper orderPriceHelper;  // 注入使用
    
    public OrderResult createOrder(CreateOrderRequest request) {
        BigDecimal price = orderPriceHelper.calculatePrice(request.getItems(), request.getUserId());
    }
}

🛠️ Utils类 - 纯工具,静态方法:

typescript 复制代码
// 纯工具类,无业务逻辑
public class DateUtils {
    
    // 静态方法,无依赖
    public static String formatDate(Date date, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }
    
    public static Date parseDate(String dateStr, String pattern) {
        // 纯字符串转换,无业务逻辑
    }
    
    public static boolean isWeekend(Date date) {
        // 纯计算逻辑
    }
}

public class StringUtils {
    
    public static boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
    
    public static String camelToSnake(String camelCase) {
        // 纯字符串转换
    }
}

// 使用方式:直接静态调用
String formatted = DateUtils.formatDate(new Date(), "yyyy-MM-dd");
相关推荐
CHENWENFEIc25 分钟前
SpringBoot论坛系统安全测试实战报告
spring boot·后端·程序人生·spring·系统安全·安全测试
重庆小透明1 小时前
力扣刷题记录【1】146.LRU缓存
java·后端·学习·算法·leetcode·缓存
博观而约取1 小时前
Django 数据迁移全解析:makemigrations & migrate 常见错误与解决方案
后端·python·django
寻月隐君2 小时前
Rust 异步编程实践:从 Tokio 基础到阻塞任务处理模式
后端·rust·github
GO兔2 小时前
开篇:GORM入门——Go语言的ORM王者
开发语言·后端·golang·go
Sincerelyplz2 小时前
【Temproal】快速了解Temproal的核心概念以及使用
笔记·后端·开源
爱上语文2 小时前
Redis基础(6):SpringDataRedis
数据库·redis·后端
Lemon程序馆2 小时前
速通 GO 垃圾回收机制
后端·go
Aurora_NeAr2 小时前
Spark SQL架构及高级用法
大数据·后端·spark
杰尼橙子2 小时前
DPDK BPF:将eBPF虚拟机的灵活性带入到了DPDK的高性能用户态
后端·性能优化