策略模式,用我这个框架好吗

250 阅读3分钟

战略

策略模式可以说是我们业务开发中使用最频繁的设计模式之一,它能让我们的代码符合开闭原则,同时业务逻辑更加内聚。

通常我们会将我们的业务逻辑抽象成一个接口,针对不同的模式,使用不同的实现

以下单场景的价格计算为例

在使用策略模式之前,我们的代码可能是这样

if(里程包){
    //计算价格逻辑为根据车辆合同价选择对应单价*购买公里数
}else if(保险){
    //保险合约中剩余天数/365*保险单价
}else if(普通商品){
    //商品单价*件数*折扣
}
...

而使用策略模式后,我们将价格计算抽象成PriceCalculateStrategy接口

public interface PriceCalculateStrategy {
    Long calculate(Object order);
}

使用时,从策略容器中获取对应策略实现,进行调用

PriceCalculateStrategy strategy = strategyContainer.get(商品类型)
price = strategy.calculate(...)

这样做的好处是,当计算逻辑需要扩展时,我新增对应的接口实现即可,不影响整体流程。

战术

在战术层面,我们需要根据使用场景来实现我们的策略容器,来获取我们的策略实现进行调用

简单的逻辑封装

在这种场景下,我们的策略逻辑不依赖于spring ioc容器,只是单纯的业务逻辑,这种场景下推荐使用枚举来实现策略模式

public enum PriceCalculateStrategyContainer{

    FRUIT(new FruitPriceCalculateStrategy()),
    VEGETABLE(new VegetablePriceCalcualteStrategy());

    private PriceCalculateStrategy priceCalculateStrategy;

    public PriceCalculateStrategy getPriceCalculateStrategy() {
        return priceCalculateStrategy;
    }

    PriceCalculateStrategyContainer(PriceCalculateStrategy priceCalculateStrategy) {
        this.priceCalculateStrategy = priceCalculateStrategy;
    }

}

调用方式如下

PriceCalculateStrategyContainer.FRUIT.getPriceCalculateStrategy().calculate(123)

依赖ioc容器的复杂模式

在spring容器中使用策略模式我们最常见的做法是

  1. 定义策略接口和策略实现
  2. 给策略实现加上特定注解
  3. 通过ApplicationContextAware从spring容器中获取所有策略实现,放到一个Map中
  4. 业务代码中从Map中获取策略实现进行调用

有没有发现你在你项目中的实现和上面的流程很相似?

在我做系统重构时,我写了很多策略模式,因此我沉淀出了一个框架来方便大家在spring容器中使用策略模式。这个策略模式框架在功能上以及稳定性上都要比自己写的强!

下面我会从术语,特性,以及基础使用来介绍我的这个框架。

术语

  1. 策略接口

    根据业务逻辑抽象的策略接口

  2. 策略实现

    策略接口的实现

  3. 策略容器

    每个策略接口会对应一个策略容器,它就是个Map,用于保存策略标识符和策略实现的关系

  4. 策略自定义注解

    策略实现上的注解,用于获取策略标识符

  5. 策略标识符

    从策略注解上解析得到,也可以手动注册,与策略实现多对一绑定

  6. 策略标识符提取逻辑

    从策略实现类上注解提取策略标识符的逻辑

特性

  1. 基础功能,策略自定义注解绑定策略实现,通过策略标识符从策略容器获取策略实现
  2. 支持默认策略,通过策略标识符获取不到策略实现,返回默认实现
  3. 策略自定义注解支持Repeatable,也就是多个标识符能绑定一个策略
  4. 支持手动注册策略,而不是通过注解的方式
  5. 提供多策略容器,一个标识符返回多个策略(比如校验场景)

基础使用

更多使用方式,见github.com/dsc-cmt/spr…,欢迎大家fork