游乐游手机版
首页/编程语言/文章详情

基于Map和Bean的策略模式Java实现详解

时间:2026-06-10 06:54
利用Spring容器将策略实现注入到Map中,通过业务标识直接匹配调用,替代传统构造方法或set方法选择策略。该方法减少上下文类维护成本,策略扩展只需在配置中心增加映射,业务侧完全解耦,并利用IoC管理策略生命周期。

策略模式堪称设计模式入门必修课,多数开发者初次学习时,往往通过构造方法或set方法选择具体策略。这种做法本身没有错误,但在实际业务中,若能结合Spring的依赖注入能力,完全可以采用更优雅、更简洁的实现方式。

直接给出结论:将策略实现交由Spring容器管理的Map + Bean方式,能够显著降低上下文类的维护复杂度。

1、关于策略模式

经典策略模式的定义与基础实现可参考菜鸟教程等常见资料,这类教程通常基于构造方法实现,清晰易懂。然而本文重点探讨的是在此之上再抽象一层,借助Spring的IoC容器来动态调度策略。

2、使用Map + Bean方式实现策略模式

核心改动点在于:不再通过set方法或构造方法显式指定具体策略实现,而是由Spring容器将所有策略实现注入到一个Map中,随后根据业务传来的标识(例如枚举值)直接匹配并调用。

下面以电商系统中常见的“商品价格计算”场景为例,完整演示具体实现步骤。

2.1 定义顶层计算价格接口

首先定义一个价格计算策略接口,该接口作为所有具体策略实现的顶层规范:

/**
 * 价格计算策略接口
 */
public interface PriceCalculatingStrategy {

    /**
     * 计算价格
     *
     * @param user   操作用户
     * @param factor 影响因素
     * @param prices 价格
     * @return 计算后的价格
     */
    BigDecimal calculatingProductPrices(User user, ProductPriceFactor factor, BigDecimal prices);
}

2.2 定义上下文

接下来是上下文类。核心要点是使用 @Resource 注入一个名为 priceStrategyMap 的Map,其中key为策略标识,value为对应的策略实现Bean。调用时,根据 factorType 从Map中取出目标策略并执行计算:

/**
 * 价格计算上下文
 */
@Component
public class PricesContext {

    @Resource(name = "priceStrategyMap")
    private Map calculatingStrategyMap;

    public BigDecimal calculating(User user, ProductPriceFactor factor, BigDecimal prices) {
        PriceCalculatingStrategy priceCalculatingStrategy = calculatingStrategyMap.get(factor.getFactorType());
        return priceCalculatingStrategy.calculatingProductPrices(user, factor, prices);
    }
}

2.3 策略注入类(组件)

策略注入环节通过 @Configuration 配置类实现策略注册中心。将VIP和邮费两种策略的Bean注入后,统一放入HashMap,并暴露为Spring管理的Bean:

@Configuration
public class PriceStrategyConfig {

    @Resource
    private VIPPriceStrategy vipPriceStrategy;

    @Resource
    private PostageStrategy postageStrategy;

    @Bean(name = "priceStrategyMap")
    public Map submitOrderStrategyMap() {
        Map strategyMap = new HashMap<>();
        strategyMap.put(FactorType.VIP.factorType, vipPriceStrategy);
        strategyMap.put(FactorType.POSTAGE.factorType, postageStrategy);
        return strategyMap;
    }

    @Getter
    enum FactorType {
        VIP(3),
        POSTAGE(2);

        FactorType(int factorType) {
            this.factorType = factorType;
        }

        private final int factorType;
    }
}

2.4 策略模式的具体实现

有了顶层接口与注册中心后,业务逻辑实现在具体策略类中。例如VIP折扣策略执行打折逻辑,而邮费策略则在商品原价基础上增加邮费金额:

@Service
public class VIPPriceStrategy implements PriceCalculatingStrategy{

    @Override
    public BigDecimal calculatingProductPrices(User user, ProductPriceFactor factor, BigDecimal prices) {
        // 这里忽略会员等级判断,用固定值测试
        return user.getId().equals(1L) ? prices.multiply(new BigDecimal("0.7")) : prices.multiply(factor.getValue());
    }
}

@Service(value = "postageStrategy")
public class PostageStrategy implements PriceCalculatingStrategy{

    @Override
    public BigDecimal calculatingProductPrices(User user, ProductPriceFactor factor, BigDecimal prices) {
        // 忽略发货地、收货地之间的邮费计算,测试用固定值
        return user.getId().equals(2L) ? prices.add(factor.getValue()) : prices;
    }
}

2.5 策略接口调用

在业务调用层,直接面向 PricesContext 上下文,通过 factorType 匹配对应策略实现,完成价格计算:

@Service
@RequiredArgsConstructor
public class ProductServiceImpl extends ServiceImpl implements ProductService {

    private final ProductPriceFactorService productPriceFactorService;
    private final PricesContext pricesContext;

    public BigDecimal calculatingProductPrices(Long productId, Integer productNum, User user) {
        // 忽略参数校验
        Product product = this.getById(productId);
        BigDecimal prices = product.getPrice().multiply(new BigDecimal(productNum));
        prices = calculatingFactor(user, productId, prices);
        return prices;
    }

    private BigDecimal calculatingFactor(User user, Long productId, BigDecimal prices) {
        List allFactorByProDuct = productPriceFactorService.getAllFactorByProDuct(productId);
        if (CollectionUtils.isNotEmpty(allFactorByProDuct)) {
            for (ProductPriceFactor factor : allFactorByProDuct) {
                prices = pricesContext.calculating(user, factor, prices);
            }
        }
        return prices;
    }
}

2.6 测试用例

基于Map+bean的策略模式实现方式

2.7 额外

最后说明,本示例基于SpringBoot + MySQL + Maven + MyBatisPlus搭建,代码编写相对随意,重点在于展示Map+Bean思路的优越性。如有不足之处,欢迎指正,共同进步。

总结

总体而言,这种实现方案具备以下几方面优势:

  • 策略注册与扩展只需在配置中心添加一个 put 操作,无需修改上下文类;
  • 业务侧仅需传入标识类型,实现完全解耦;
  • 借助Spring的IoC特性管理策略Bean生命周期,避免手动创建对象的繁琐。

希望该思路能为正在寻找更规范策略模式实现方案的开发者带来启发。

来源:https://www.jb51.net/program/3654180ee.htm
上一篇SpringBoot集成TDengine的完整使用指南 下一篇JVM崩溃FatalError问题排查与解决方案
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
IDEA中SpringBoot项目热部署实现指南
编程语言 · 2026-07-11

IDEA中SpringBoot项目热部署实现指南

Springboot项目在IDEA中实现热部署需依次完成:开启自动编译(静态与动态编译)、启用热部署策略、引入spring-boot-devtools依赖、关闭浏览器缓存,最后启动测试即可生效,省去手动重启时间,大幅提升开发效率。

Java实现Excel转JSON的代码详解
编程语言 · 2026-07-11

Java实现Excel转JSON的代码详解

使用Java结合FreeSpire XLS库可自动将Excel转为JSON,通过读取工作表并映射为键值对,高效支持数据迁移、报表导出与系统对接,大幅提升效率并消除手动录入错误。

Golang高效布谷鸟过滤器多字符集字符串过滤
编程语言 · 2026-07-11

Golang高效布谷鸟过滤器多字符集字符串过滤

布谷鸟过滤器支持删除操作,通过指纹截断与双哈希定位实现多字符集高效过滤。指纹截断需采用fnv64a或xxhash快速哈希并取低8位,桶索引使用独立双哈希避免假阳性。并发安全需以固定数组配合sync atomic实现。

Java使用Poi-tl按Word模板生成动态表格
编程语言 · 2026-07-11

Java使用Poi-tl按Word模板生成动态表格

Poi-tl是Word导出工具,文档周全,支持多级合并表头生成。通过{{text}}、{{?var}}、{{ table}}标签处理模板,传入TableRenderData对象即可动态渲染表格。示例展示用户信息表格生成,并提供工具类消除表格首行缩进,确保格式正确。

Go语言微服务集成Swagger生成交互式API文档完整教程
编程语言 · 2026-07-11

Go语言微服务集成Swagger生成交互式API文档完整教程

在Go微服务中集成Swagger常见四大问题:swaginit初始化失败需确保存在packagemain及注释;SwaggerUI加载失败因路由映射错误或未导入docs;@Param注解必须严格遵循格式;部署后接口文档显示localhost因硬编码host,应删除或通过环境变量动态注入。