美文网首页
从if-else到策略注册表的演进

从if-else到策略注册表的演进

作者: 了不起的ACER | 来源:发表于2025-06-20 04:25 被阅读0次

概述

本文档基项目中的StrategyRegistry实现,深入分析从传统if-else条件判断到现代策略注册表模式的演进过程。

演进历程

第一阶段:简单if-else(史前时代)

最原始的条件分发方式,适用于简单场景:

public class Service {
    public ResponseDto exec(String type, Object data) {
        if ("1".equals(type)) {
            return handle1();
        } else if ("2".equals(type)) {
            return handle2();
        } else {
            throw new ServiceException("不支持的认证类型: " + type);
        }
    }
}

特点:

  • 简单直观
  • 逻辑集中
  • 适合2-3个分支

问题:

  • 违反开闭原则
  • 扩展需要修改原有代码
  • 复杂度随分支数量线性增长

第二阶段:复杂if-else链(古代)

随着业务复杂度增加,条件判断变得复杂:

public class Service {
    public ResponseDto exec(ActionType actionType, Command command) {
        if (ActionType.A.equals(actionType)) {
            if (command.getLoginDto().getType() == Type.1) {
                return handle1(command.getDto());
            } else if (command.getDto().getType() == Type.2) {
                return handle2(command.getDto());
            }
        } else if (ActionType.B.equals(actionType)) {
            if (command.getDto().getType() == Type.3) {
                return handle3(command.getDto());
            } else if (command.getDto().getype() == Type.4) {
                return handle4(command.getDto());
            }
        }
        throw new ServiceException("不支持的认证类型: " + actionType);
    }
}

问题加剧:

  • 代码可读性急剧下降
  • 维护成本高
  • 容易出现遗漏分支
  • 测试复杂度指数增长

第三阶段:switch优化(近代)

使用switch语句优化可读性:

public class Service {
    public ResponseDto exec(ActionType actionType, Command command) {
        return switch (actionType) {
            case A -> handle1(command);
            case B -> handle2r(command);
            default -> throw new ServiceException("不支持的认证类型: " + actionType);
        };
    }
}

改进:

  • 可读性提升
  • 编译器检查遗漏分支
  • 性能略有提升

仍存在问题:

  • 依然违反开闭原则
  • 方法体臃肿
  • 难以进行单元测试

第四阶段:简单策略模式(现代早期)

引入策略模式,实现基本的策略分发:

public class hService {
    private final Map<ActionType, Strategy> strategies;

    public Service() {
        strategies = Map.of(
                ActionType.A, new Strategy(),
                ActionType.B, new Strategy()
        );
    }

    public ResponseDto henticate(ActionType actionType, Command command) {
        Strategy strategy = strategies.get(actionType);
        if (strategy == null) {
            throw new ServiceException("不支持的认证类型: " + actionType);
        }
        return strategy.execute(command);
    }
}

优势:

  • 符合开闭原则
  • 策略独立可测试
  • O(1)时间复杂度

局限:

  • 硬编码策略映射
  • 不支持动态注册
  • 缺乏优先级管理

第五阶段:策略注册表(现代)

基于Spring容器的自动化策略注册表:

@Component
public class StrategyRegistry {

    private final Map<ActionType, Strategy> strategyMap = new HashMap<>();
    private Map<ActionType, Strategy> immutableStrategyMap;

    @owired(required = false)
    private List<Strategy> strategies = new ArrayList<>();

    @PostConstruct
    public void initRegistry() {
        // 按优先级排序
        strategies.sort(Comparator.comparingInt(Strategy::getPriority));

        // 自动注册所有策略实现
        for (Strategy strategy : strategies) {
            registerStrategy(strategy);
        }

        // 创建不可变视图
        immutableStrategyMap = Map.copyOf(strategyMap);
    }

    public Strategy getStrategy(ActionType actionType) {
        Strategy strategy = immutableStrategyMap.get(actionType);
        if (strategy == null) {
            throw new ServiceException("未找到认证类型 " + actionType + " 对应的策略");
        }
        return strategy;
    }
}

现代化特性:

  • 自动发现和注册
  • 优先级管理
  • 不可变视图保护
  • 完整的生命周期管理
  • 详细的日志记录

推荐资源

  • 《设计模式:可复用面向对象软件的基础》- 策略模式详解
  • 《重构:改善既有代码的设计》- 消除if-else链的重构技巧
  • 《架构整洁之道》- 依赖倒置原则在策略模式中的应用

-end-

相关文章

网友评论

      本文标题:从if-else到策略注册表的演进

      本文链接:https://www.haomeiwen.com/subject/bcllgjtx.html