SpringBoot策略模式通用方案

SpringBoot策略模式通用方案

策略模式简介

策略模式(Strategy Pattern)是软件设计模式中的一种行为模式

作为软件设计模式的一种,其目的是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性

从软件工程的角度来讲,运用策略模式这样的设计模式最终目的是为了设计出高内聚低耦合的高质量软件。

策略模式理解

策略模式:策略二字,顾名思义,是为了实现某种目标而制定的方法,就像诸葛亮隆中对为刘备制定的三分天下的策略。

而在软件开发中,以面向对象为例,有时候对象需要获取某种结果,在此期间需要不同的方法策略

现实中举例子:比如说去超市买东西想要花钱,对象可以选择微信支付、支付宝支付、云闪付支付等等方式

我们把这一系列的方法抽象出来的一种方式,规范化演变成了策略模式

在porcessOn中看到的觉得不错,如下图所示:

策略模式图

  • Strategy是接口,定义策略的抽象方法

  • Strategy1和Strategy2是接口实现,实现不同的策略

  • Context作为策略上下文,用于管理和使用策略,作为策略的管理者,有很好的拓展性,比如说策略需要一些公共的前置校验、后置操作等。

上面这个是标准的Java中的实现,以下内容又结合了工厂模式,将Context改为一个工厂,用于生产和交付策略方法,使用更为灵活。

策略模式结合SpringBoot

  1. 在SpringBoot项目中,主要使用到了spring的IoC(Inversion of Control),我们将创建对象交给了spring容器管理;

    策略模式中我们就可以将不同策略的对象交给spring容器来管理,不同方法实现加上注解如:@Component

  2. 我们需要更方便的注册使用,仅仅交给spring容器是不够的,所以可以结合工厂模式,把不同的策略注册到工厂的map中去统一管理

    通过实现spring的容器初始化的接口implements InitializingBean,实现afterPropertiesSet方法,在bean初始化完成时将其注册到工厂

  3. 在使用时候,我们通过工厂根据类型来获取不同的策略方法,来执行策略,至此每次修改和开发策略,只更改不同的strategy,而无需修改业务上下文,做到了一定程度的解耦,而不同的策略在不同的实现类,互不干扰,内聚程度也得到了提升,对于软件工程的质量也有一定的提升。

需要注意:

  1. 通用的策略模式一般需要确保所有的策略的输入和输出是确定的,以去超市买东西举例,买东西需要的输入是支付的金额等信息,输出是支付结果成功失败等信息是确定的,否则的话需要结合泛型来使用了。
  2. 通过不同的类型区分,来执行不同的策略,以去超市买东西举例,类型可分为:a微信b支付宝和c云闪付,a对应微信支付的策略方法,b对应支付保的策略方法。

代码实现

策略接口

定义好一组策略方法共同的入参出参的规范即可

/**
 * 策略接口
 * @author HB、ocean
 * @date 2024/08/22
 */
public interface Strategy {

    /**
     * 策略注册方法
     * 注:策略实现类需实现InitializingBean方法,编写afterPropertiesSet抽象方法的实现,调用此方法,进行策略注册
     *
     * @param code
     */
    default void afterPropertiesSet(String code) {
        StrategyFactory.register(code, this);
    }

    /**
     * 业务逻辑A
     *
     * @param reqDTO 业务入参DTO
     * @return {@link RespDTO}
     */
    RespDTO businessA(ReqDTO reqDTO);

    /**
     * 业务逻辑B
     *
     * @param reqDTO 业务入参DTO
     * @return {@link RespDTO}
     */
    RespDTO businessB(ReqDTO reqDTO);

}

策略实现

实现策略接口,实现抽象方法,并且将不同的策略注册到策略上下文工厂

示例只写了一个默认策略实现,不同的策略类似就不写了哈

/**
 * 默认策略实现
 * @author HB、ocean
 * @date 2024/08/23
 */
@Component
@Slf4j
public class DefaultStrategyImpl implements Strategy, InitializingBean {
    
    @Override 
    RespDTO businessA(ReqDTO reqDTO) {
        // 业务a策略实现 todo
    }

    @Override
    RespDTO businessB(ReqDTO reqDTO) {
        // 业务b策略实现 todo
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        afterPropertiesSet(Constant.DEFAULT_STRATEGY_TYPE);
    }

}

策略工厂

用于管理策略,执行策略

/**
 * 策略工厂类
 * (根据类型来区分,注册和获取不同的策略方法)
 * @author HB、ocean
 * @date 2024/08/22
 */
@Slf4j
public final class StrategyFactory {

    /**
     * 私有化构造器
     */
    private StrategyFactory() {

    }

    /**
     * 集合存储,key 策略类型,value 策略对象
     */
    private static final Map<String, Strategy> STRATEGY_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();

    /**
     * 提供获取策略的方法
     *
     * @param bankCode
     * @return {@link Strategy}
     */
    public static Strategy getStrategy(String type) {
        // todo 可以进行前置校验 
        Strategy sendService = STRATEGY_CONCURRENT_HASH_MAP.get(type);
        return sendService;
    }

    /**
     * 在Bean属性初始化后执行该方法
     *
     * @param type   类型
     * @param strategy
     */
    public static void register(String type, Strategy strategy) {
        LOGGER.info("注册type: {},对应的处理策略...", type);
        STRATEGY_CONCURRENT_HASH_MAP.put(type, strategy);
    }

}

总结

策略模式看似繁琐的一系列规范,涉及到接口、实现、上下文,但实际上对于代码质量的提升功不可没……

  • 想象下,如果不用策略模式,我们在业务代码中使用一些if-else,前期开发进度快了,但随着需求增加,代码行数增多,业务逻辑耦合会非常高,不太利于后期的维护和更改。

  • 反观在策略模式的规范下,哪个策略改了,我只改那个策略的实现类;如果修改了公共的内容,修改接口或者策略上下文工厂即可;新增和删除策略,都无需修改业务代码。

当然这也只是作者的一方观点(ps:阿里规约中也有提到当超过 3 层的 if-else 的逻辑判断代码可以使用策略模式来实现。
欢迎各位大佬提出意见😄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值