策略模式:Spring Bean策略与枚举 Lambda策略

1-使用目的:

  • 替换大量的 if-else 或 switch-case 语句,让代码更简洁易读
  • 新增推送类型时只需添加新的策略实现,不需要修改现有业务逻辑,便于维护

2-两种常见的策略模式

2-1.Spring Bean策略模式

定义枚举:用于管理推送的类型,主要是维护一个字典,还有个好处就是枚举天然的编译期检查,出现问题会直接飘红的,必须修改了才能启动

java 复制代码
@Getter
@AllArgsConstructor
public enum DataPushType {

    ORDER_CREATE(1, "订单创建推送"),
    ORDER_CANCEL(2, "订单取消推送"),
    ORDER_FINISH(3, "订单完成推送");

    private final int code;
    
    private final String desc;

    public static DataPushType of(int code) {
        for (DataPushType type : values()) {
            if (type.code == code) {
                return type;
            }
        }
        throw new IllegalArgumentException("未知推送类型: " + code);
    }
}

策略注册接口:后续的具体实现类,都要实现这个接口

java 复制代码
public interface DataPushStrategy {

    /**
     * 当前策略支持的推送类型
     */
    DataPushType getType();

    /**
     * 处理推送数据
     */
    void handlePushData(String data);
}

策略具体实现:以OrderCreate示例

java 复制代码
// OrderCreate示例
@Component
@Slf4j
public class OrderCreatePushStrategy implements DataPushStrategy {

    @Override
    public DataPushType getType() {
        return DataPushType.ORDER_CREATE;
    }

    @Override
    public void handlePushData(String data) {
        log.info("处理【订单创建】推送,data={}", data);
        // 具体业务逻辑
    }
}

策略manager:用于注册和管理策略,具体使用的就是这个类,外部注入这个策略manager Bean,使用对应方法即可

java 复制代码
@Component
@Slf4j
public class DataPushStrategyManager {

    private final Map<DataPushType, DataPushStrategy> strategyMap =
            new EnumMap<>(DataPushType.class);

    // 构造函数,Spring会注入所有实现DataPushStrategy的实现类
    public DataPushStrategyManager(List<DataPushStrategy> strategies) {

        for (DataPushStrategy strategy : strategies) {
            DataPushType type = strategy.getType();

            if (strategyMap.containsKey(type)) {
                throw new IllegalStateException("重复的推送策略定义: " + type);
            }
            // 放入策略map中
            strategyMap.put(type, strategy);
            log.info("注册推送策略: type={}, class={}", type, strategy.getClass().getSimpleName());
        }
    }

    // 通过策略typecode,来执行对应的策略
    public void execute(int typeCode, String data) {
        DataPushType type = DataPushType.of(typeCode);
        execute(type, data);
    }

    // 通过DataPushType,来执行对应的策略
    public void execute(DataPushType type, String data) {
        DataPushStrategy strategy = strategyMap.get(type);
        if (strategy == null) {
            throw new IllegalArgumentException(
                    "未找到推送策略: " + type);
        }
        strategy.handlePushData(data);
    }
}

调用:

bash 复制代码
1.注入strategyManager Bean
2.直接调用strategyManager.execute(typeCode, data);

2-2.枚举策略模式

定义枚举:相比以前的那个就是加了一个参数,主要是根据对应的类型,然后该调用Bean里的哪个方法

java 复制代码
@Getter
@AllArgsConstructor
public enum DataPushStrategyEnum {

    ORDER_CREATE(1, "订单创建推送", (data, service) -> service.handleOrderCreate(data)),

    ORDER_CANCEL(2, "订单取消推送", (data, service) -> service.handleOrderCancel(data)),

    ORDER_FINISH(3, "订单完成推送", (data, service) -> service.handleOrderFinish(data));

    private final int code;

    private final String desc;

    /**
     * 具体执行逻辑(策略)
     */
    private final BiConsumer<String, DataPushService> executor;

    private static final Map<Integer, DataPushStrategyEnum> CACHE =
            Arrays.stream(values())
                    .collect(Collectors.toMap(DataPushStrategyEnum::getCode, v -> v));

    public static DataPushStrategyEnum of(int code) {
        DataPushStrategyEnum strategy = CACHE.get(code);
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的推送类型: " + code);
        }
        return strategy;
    }

    public void execute(String data, DataPushService service) {
        executor.accept(data, service);
    }
}

主要的Bean:具体的业务实现

java 复制代码
@Service
@Slf4j
public class DataPushService {

    public void handleOrderCreate(String data) {
        log.info("处理【订单创建】推送,data={}", data);
        // 原 OrderCreatePushStrategy 的逻辑
    }

    public void handleOrderCancel(String data) {
        log.info("处理【订单取消】推送,data={}", data);
        // 原 OrderCancelPushStrategy 的逻辑
    }

    public void handleOrderFinish(String data) {
        log.info("处理【订单完成】推送,data={}", data);
        // 原 OrderFinishPushStrategy 的逻辑
    }
}

构建调用层:再包一层,外部注入这个Bean去调用

java 复制代码
@Service
public class DataPushFacade {

    private final DataPushService dataPushService;
	// spring构造时会自动的注入dataPushService
    public DataPushFacade(DataPushService dataPushService) {
        this.dataPushService = dataPushService;
    }

    public void push(int typeCode, String data) {
        DataPushStrategyEnum.of(typeCode)
                .execute(data, dataPushService);
    }
}

这种只适合业务不复杂的简单情况,一旦业务复杂,需要需要注入多个依赖,频繁修改的业务,就不要用这个了,还是用传统的Spring Bean方式

PS:

bash 复制代码
(data, service) -> service.handleOrderFinish(data)
#是一个实现了 BiConsumer<String, DataPushService> 的 Lambda 表达式实例

从 Java 语义上讲:

复制代码
BiConsumer<String, DataPushService> executor =
        (data, service) -> service.handleOrderFinish(data);

等价于(概念等价,不是字节码等价):

java 复制代码
BiConsumer<String, DataPushService> executor =
    new BiConsumer<String, DataPushService>() {
    @Override
    public void accept(String data, DataPushService service) {
        service.handleOrderFinish(data);
    }
};

只是Java 8之后,用Lambda语法糖写出来的

相关推荐
知兀5 小时前
【MybatisPlus】后端用枚举类,数据库用tinyint,存在枚举类型转换
java
StockTV5 小时前
印度股票实时数据 NSE和BSE的实时行情、K 线及指数数据
java·开发语言·spring boot·python
User_芊芊君子5 小时前
【OpenAI 把 AI 玩明白了】:自主推理 + 动态知识图谱,这 4 个技术突破要颠覆行业
java·人工智能·知识图谱
今夕资源网5 小时前
Windows 上安装 Claude Code并且接入DeepSeekV4-Pro的Max模式和激活1M上下文
windows
c++之路5 小时前
C++20概述
java·开发语言·c++20
Championship.23.245 小时前
Linux Top 命令族深度解析与实战指南
java·linux·服务器·top·linux调试
橘子海全栈攻城狮6 小时前
【最新源码】养老院系统管理A013
java·spring boot·后端·web安全·微信小程序
敖正炀6 小时前
反模式与排查宝典:Spring Boot 自动配置与核心机制的常见陷阱
spring boot
逻辑驱动的ken6 小时前
Java高频面试考点18
java·开发语言·数据库·算法·面试·职场和发展·哈希算法