使用策略模式进行设计大量相同业务逻辑和少量不同的业务逻辑

183 阅读3分钟

1. 设计思想

  1. 策略模式:将 30 种逻辑相同的手续定义为 通用策略,其余 8 种特殊手续各自实现 特定策略

  2. 工厂模式:通过工厂类根据手续类型动态选择对应的策略。

  3. 分层设计

    • Controller 层:接收请求,路由到对应策略。
    • Service 层:策略接口定义核心逻辑,不同策略实现差异化处理。
    • DAO 层:不同手续对应不同实体和 Repository,支持分表存储。

2. 代码实现

步骤 1:定义手续类型枚举

public enum ProcedureType {
    COMMON_TYPE_1, COMMON_TYPE_2, ..., // 30 种通用类型
    SPECIAL_TYPE_1, SPECIAL_TYPE_2, ... // 8 种特殊类型
}

步骤 2:定义策略接口

public interface ProcedureStrategy {
    // 标识该策略支持的手续类型
    boolean supports(ProcedureType type);
    
    // 保存逻辑
    void save(ProcedureDTO dto);
    
    // 查询逻辑
    ProcedureDTO query(Long id);
}

步骤 3:实现通用策略(处理 30 种逻辑相同的手续)

@Component
public class CommonProcedureStrategy implements ProcedureStrategy {
    // 支持的 30 种通用类型
    private static final Set<ProcedureType> SUPPORTED_TYPES = 
        Set.of(ProcedureType.COMMON_TYPE_1, ProcedureType.COMMON_TYPE_2, ...);
​
    @Autowired
    private CommonProcedureRepository commonRepo;
​
    @Override
    public boolean supports(ProcedureType type) {
        return SUPPORTED_TYPES.contains(type);
    }
​
    @Override
    public void save(ProcedureDTO dto) {
        CommonProcedure entity = convertToEntity(dto);
        commonRepo.save(entity);
    }
​
    @Override
    public ProcedureDTO query(Long id) {
        CommonProcedure entity = commonRepo.findById(id).orElseThrow();
        return convertToDTO(entity);
    }
​
    // DTO 与 Entity 转换逻辑
    private CommonProcedure convertToEntity(ProcedureDTO dto) { ... }
    private ProcedureDTO convertToDTO(CommonProcedure entity) { ... }
}

步骤 4:实现特殊策略(以 SPECIAL_TYPE_1 为例)

@Component
public class SpecialProcedure1Strategy implements ProcedureStrategy {
    @Autowired
    private SpecialProcedure1Repository specialRepo;
​
    @Override
    public boolean supports(ProcedureType type) {
        return type == ProcedureType.SPECIAL_TYPE_1;
    }
​
    @Override
    public void save(ProcedureDTO dto) {
        SpecialProcedure1 entity = convertToEntity(dto);
        specialRepo.save(entity);
    }
​
    @Override
    public ProcedureDTO query(Long id) {
        SpecialProcedure1 entity = specialRepo.findById(id).orElseThrow();
        return convertToDTO(entity);
    }
​
    // 转换逻辑
    private SpecialProcedure1 convertToEntity(ProcedureDTO dto) { ... }
    private ProcedureDTO convertToDTO(SpecialProcedure1 entity) { ... }
}

步骤 5:策略工厂(动态路由策略)

@Component
public class ProcedureStrategyFactory {
    private final List<ProcedureStrategy> strategies;
​
    // 自动注入所有策略实现
    @Autowired
    public ProcedureStrategyFactory(List<ProcedureStrategy> strategies) {
        this.strategies = strategies;
    }
​
    public ProcedureStrategy getStrategy(ProcedureType type) {
        return strategies.stream()
            .filter(s -> s.supports(type))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("未支持的手续类型: " + type));
    }
}

步骤 6:Controller 层(对外接口)

@RestController
@RequestMapping("/procedures")
public class ProcedureController {
    @Autowired
    private ProcedureStrategyFactory strategyFactory;
​
    @PostMapping
    public void saveProcedure(@RequestBody ProcedureDTO dto) {
        ProcedureType type = dto.getType();
        ProcedureStrategy strategy = strategyFactory.getStrategy(type);
        strategy.save(dto);
    }
​
    @GetMapping("/{id}")
    public ProcedureDTO getProcedure(@PathVariable Long id, @RequestParam ProcedureType type) {
        ProcedureStrategy strategy = strategyFactory.getStrategy(type);
        return strategy.query(id);
    }
}

步骤 7:实体与 Repository 定义

  • 通用手续实体

    @Entity
    @Table(name = "common_procedure")
    public class CommonProcedure {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String commonField1;
        private String commonField2;
        // 公共字段...
    }
    
  • 特殊手续实体

    @Entity
    @Table(name = "special_procedure_1")
    public class SpecialProcedure1 {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String specialField1;
        // 特殊字段...
    }
    
  • Repository 接口

    public interface CommonProcedureRepository extends JpaRepository<CommonProcedure, Long> {}
    public interface SpecialProcedure1Repository extends JpaRepository<SpecialProcedure1, Long> {}
    

3. 关键优化点

  1. 动态路由:通过策略工厂自动匹配类型与策略,无需硬编码 if-else

  2. 代码复用

    • 通用策略处理 30 种相似逻辑,特殊策略仅关注差异部分。
    • 使用 Lombok 或 MapStruct 简化 DTO/Entity 转换。
  3. 扩展性:新增手续类型时,只需添加新策略实现,无需修改已有代码。

  4. 数据隔离:不同手续存储到不同表,避免单表过大。


4. 扩展建议

  • 模板方法模式:如果通用逻辑中有部分步骤需定制,可在 CommonProcedureStrategy 中定义模板方法。
  • 异步处理:对耗时操作(如备案审批),可在策略中引入 @Async 异步处理。
  • 日志与监控:在策略工厂中添加日志,记录各策略的调用频率和性能。