项目经理让我利用策略模式提升Spring Boot应用的代码质量,我表示...🫨🫨

📣前言


在Spring Boot中使用策略模式(Strategy Pattern)是一种常见的设计模式实践,它允许在运行时选择算法的行为。策略模式定义了一系列的算法,并将每个算法封装起来,使它们可以互换。这样做的好处是使算法的变化独立于使用算法的客户;说白了策略模式是一种行为设计模式,它允许在运行时选择算法的行为。通过定义一系列可互换的算法,策略模式让算法的变化独立于使用算法的客户。

那么,具体如何实现呢?这将又会是干货满满的一期,全程无尿点不废话只抓重点教,具有非常好的学习效果,拿好小板凳准备就坐!希望学习的过程中大家认真听好好学,学习的途中有任何不清楚或疑问的地方皆可评论区留言或私信,bug菌将第一时间给予解惑,那么废话不多说,直接开整!Fighting!!

🌊环境说明

开发工具: IDEA_2021.3 JDK版本: JDK_1.8 Spring Boot版本:2.3.1.RELEASE Maven版本:3.8.2

正文

以下是在Spring Boot中实现策略模式的基本步骤:

定义策略接口

  1. 定义策略接口

创建一个策略接口,它定义了所有策略必须实现的方法,例如定义了一个方法 execute(),它是一个没有参数、返回类型为 void 的方法。

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:32
 */
public interface Strategy {
    public void execute();
}

总结来说,Strategy 接口是策略模式的一个简单而强大的实现,它允许算法的可选性和可互换性,从而提高了代码的灵活性和可维护性。

实现具体策略

  1. 实现具体策略

为每个策略创建一个类,实现策略接口。这里我们就定义仨个,分别为策略A、策略B和其他策略。策略接口定义如下,仅供参:

StrategyA.java

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:32
 */
public class StrategyA implements Strategy {

    @Override
    public void execute() {
        // 实现策略A的具体行为
        System.out.println("执行策略A!");
    }
}

StrategyB.java

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:32
 */
public class StrategyB implements Strategy {

    @Override
    public void execute() {
        // 实现策略B的具体行为
        System.out.println("执行策略B!");
    }
}

StrategyOther.java

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:32
 */
public class StrategyOther implements Strategy {

    @Override
    public void execute() {
        // 实现策略other的具体行为
        System.out.println("执行策略other!");
    }
}

以上三个策略接口就定义好了,其中我没有具体些策略执行逻辑,只是通过控制台打印信息模拟策略执行了对应策略逻辑,若是实际开发中,大家就按实际的业务逻辑进行代码实现即可。

总的来说,策略模式允许定义一系列算法,把它们一个个封装起来,并使它们可以相互替换。在这些例子中,StrategyA类提供了一种算法的实现,即打印一条消息。如果需要另一种行为,可以创建另一个实现了Strategy接口的类(比如StrategyB、StrategyOther等),并在该类中提供不同的execute方法实现。然后,可以在运行时动态地选择使用哪个策略。

创建上下文类

  1. 创建上下文类

由于客户端代码通常会有一个上下文(Context),它包含一个 Strategy 接口类型的引用。在运行时,根据需要选择并设置具体的策略实现。客户端代码可以通过调用 execute 方法来执行策略,而无需关心具体的策略实现细节。为此,我们创建一个上下文类,它包含一个策略对象,并允许在运行时更改策略。实现代码如下:仅供参考

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:32
 */
public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void executeStrategy() {
        strategy.execute();
    }
}

总结来说,Context 类提供了一个执行策略的接口,它允许客户端代码在运行时选择和更改策略,而不需要修改使用这些策略的上下文代码。这种模式提高了代码的灵活性和可维护性,因为它将策略的选择和实现从上下文逻辑中解耦出来。

配置Spring Boot

  1. 配置Spring Boot

在Spring Boot应用中,你可以使用@Configuration@Bean注解来配置策略实现,并将其注册为Spring容器中的Bean。其中,使用@Configuration注解,表明它是一个Spring配置类,用于定义应用程序的bean配置。在这个配置类中,定义了三个bean,分别是strategyA 、strategyB 和 strategyOther。这三个bean分别对应于 Strategy 接口的三个不同实现:StrategyA 、StrategyB 和 StrategyOther。实现代码如下:仅供参考

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:33
 */
@Configuration
public class StrategyConfig {
    @Bean
    public Strategy strategyA() {
        return new StrategyA();
    }

    @Bean
    public Strategy strategyB() {
        return new StrategyB();
    }

    @Bean
    public Strategy strategyOther() {
        return new StrategyOther();
    }
}

其中,@Bean注解用于定义一个bean。当Spring容器启动时,它会扫描所有带有@Configuration注解的类,并调用这些类中所有带有@Bean注解的方法。这些方法的返回值将成为Spring容器中的bean。方法的名称通常作为bean的默认名称。

因此,strategyA()方法创建的bean将默认被命名为strategyA,strategyB()方法创建的bean将默认被命名为strategyB,以此类推。对于@Bean注解的方法可以有参数,也可以没有参数,可有可无。在这个例子中,strategyA()、strategyB()和strategyOther()方法都没有参数,这意味着它们每次被调用时都会创建一个新的bean实例。

使用策略

  1. 使用策略

在你的应用中,你可以根据需要注入并使用不同的策略,说白了就是为了根据传入的策略名称执行相应的策略。实现代码如下:仅供参考

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:33
 */
@Service
public class StrategyService {
    @Autowired
    private ApplicationContext applicationContext;

    public void executeStrategy(String strategyName) {
        Strategy strategy = null;
        if ("A".equals(strategyName)) {
            strategy = applicationContext.getBean("strategyA", Strategy.class);
        } else if ("B".equals(strategyName)) {
            strategy = applicationContext.getBean("strategyB", Strategy.class);
        }else{
            strategy = applicationContext.getBean("strategyOther", Strategy.class);
        }

        if (strategy != null) {
            Context context = new Context(strategy);
            context.executeStrategy();
        }
    }
}

在上段代码中,@Service 注解表明这个类是一个Spring服务组件,Spring容器会创建这个类的实例并管理其生命周期。这样,其他组件就可以通过依赖注入(DI)来使用 StrategyService 提供的功能。而@Autowired 注解用于自动注入Spring容器中的 ApplicationContext 实例。其中,ApplicationContext 是Spring的核心接口,提供了许多方法来管理bean,如获取bean实例、发布事件等。 而对于Context类,在构造函数中接收策略实例,然后 executeStrategy() 方法会调用这个策略实例的 execute()方法来执行具体的算法。

对于executeStrategy方法,我做如下几点解释:

  • executeStrategy() 方法接受一个策略名称 strategyName 作为参数,并根据这个名称来选择并执行相应的策略。
  • 方法内部首先定义了一个 Strategy 类型的变量 strategy,它将用来存储获取到的策略实例。
  • 接着,我们使用 if-else 判断语句根据传入的 strategyName 来获取对应的策略bean。这里假设 strategyA 和 strategyB 是在配置类 StrategyConfig 中定义的bean名称。
  • 如果 strategyName 是 "A" 或 "B",则通过 applicationContext.getBean 方法获取对应的策略实例。如果名称不匹配,假设有一个默认的策略 "strategyOther" 被获取。
  • 如果成功获取到策略实例(strategy != null),则创建一个 Context 类的实例,并将策略实例传入。然后调用 Context 类的 executeStrategy() 方法来执行策略。

总结来说,StrategyService 类通过Spring的依赖注入和应用上下文来动态选择和执行不同的策略,这是策略模式在Spring框架中的一个应用示例。

测试策略

  1. 测试策略

接着我们定义一个测试代码或者控制器中,调用服务方法并传入不同的策略名称来测试策略模式。这里我们就使用Spring MVC的@RestController注解来定义一个RESTful控制器。这个控制器提供了一个HTTP GET接口,用于执行策略模式中的不同策略。实现代码如下:仅供参考

java 复制代码
/**
 * @Author bug菌
 * @Date 2024-04-08 16:34
 */
@RestController
public class StrategyController {

    @Autowired
    private StrategyService strategyService;

    @GetMapping("/execute/{strategyName}")
    public String executeStrategy(@PathVariable String strategyName) {
        strategyService.executeStrategy(strategyName);
        return "Strategy executed: " + strategyName;
    }
}

对应@RestController注解,它是一个特殊的控制器注解,它是@Controller@ResponseBody的组合。它表明这个类是一个控制器,其方法返回值会自动序列化为JSON或其他格式的响应体,而不是视图名或模板路径。这意味着客户端将直接收到数据,而不是HTML页面。对于executeStrategy()方法:它接受一个名为strategyName的参数,该参数通过URL传递。方法内部调用strategyServiceexecuteStrategy()方法,并传入策略名称。方法返回一个字符串,格式为"Strategy executed: "加上策略名称。这个字符串将被自动序列化为JSON或其他格式的响应体,并发送给客户端。最后该接口请求返回值的是一个描述性字符串,它告诉客户端策略执行的结果。在实际应用中,你可能会返回更复杂的对象或数据结构,而不是简单的字符串。

通过上述步骤,你可以在Spring Boot应用中灵活地使用策略模式,根据用户请求或其他条件动态地改变算法行为。这种模式提高了代码的可扩展性和可维护性,并且可以根据需求轻松添加新的策略实现。

接口测试

  1. 接口测试

接着,我们就根据如上定义的接口来进行一波本地测试,检验下是否都达到了预期目的,能够根据所传入的参数执行对应的策略;测试记录如下,仅供参考:

执行测试前,我们先重启项目,让我们刚写的代码都生效。然后检查下指定的环境及启动端口是多少:

启动项目成功的表现:

1、参数传入"A"

接着,我们通过接口传参的形式,先传入个"A",演示如下:http://localhost:8080/execute/A

返回到项目中,查验下控制台,是否是执行了对应A策略的逻辑?

上述结果很明显是执行成功了!即根据用户请求或其他条件动态地改变算法行为,动态的执行对应的策略逻辑。

2、参数传入"B"

与上述测试流程一直,这里我们就直接演示及展示结果。传入个"B",演示如下:http://localhost:8080/execute/B

测试结果展示如下:

3、参数传入"C"

与上述测试流程一致,这里我们就直接演示及展示结果。传入个"C",而实际中,我们并没有定义策略C,预期结果就是执行默认策略Other。演示如下:http://localhost:8080/execute/C

测试结果展示如下:

综上所述三次测试实验,完美的验证了一个目的,就是可动态的执行策略,只需要根据用户请求或其他条件,即可动态地改变算法行为。这种提升代码质量的设计思路,你们学会了吗??

... ...

ok,以上就是我这期的全部内容啦。每篇都是实打实的项目实战经验所撰。只要你每天学习一个奇淫小知识,日积月累下去,你一定能成为别人眼中的大佬的!功不唐捐,久久为功!

「赠人玫瑰,手留余香」,咱们下期拜拜~~

本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

相关推荐
编码浪子3 分钟前
构建一个rust生产应用读书笔记7-确认邮件2
开发语言·后端·rust
Ch.yang4 分钟前
【Spring】 Bean 注入 HttpServletRequest 能保证线程安全的原理
java·spring·代理模式
web150850966416 分钟前
基于Mysql、JavaScript、PHP、ajax开发的MBTI性格测试网站(前端+后端)
java
昙鱼13 分钟前
springboot创建web项目
java·前端·spring boot·后端·spring·maven
eternal__day14 分钟前
数据结构(哈希表(中)纯概念版)
java·数据结构·算法·哈希算法·推荐算法
天之涯上上18 分钟前
JAVA开发 在 Spring Boot 中集成 Swagger
java·开发语言·spring boot
2402_8575834919 分钟前
“协同过滤技术实战”:网上书城系统的设计与实现
java·开发语言·vue.js·科技·mfc
白宇横流学长20 分钟前
基于SpringBoot的停车场管理系统设计与实现【源码+文档+部署讲解】
java·spring boot·后端
APP 肖提莫23 分钟前
MyBatis-Plus分页拦截器,源码的重构(重构total总数的计算逻辑)
java·前端·算法
kirito学长-Java25 分钟前
springboot/ssm太原学院商铺管理系统Java代码编写web在线购物商城
java·spring boot·后端