📣前言
在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中实现策略模式的基本步骤:
定义策略接口
- 定义策略接口:
创建一个策略接口,它定义了所有策略必须实现的方法,例如定义了一个方法 execute(),它是一个没有参数、返回类型为 void 的方法。
java
/**
* @Author bug菌
* @Date 2024-04-08 16:32
*/
public interface Strategy {
public void execute();
}
总结来说,Strategy 接口是策略模式的一个简单而强大的实现,它允许算法的可选性和可互换性,从而提高了代码的灵活性和可维护性。
实现具体策略
- 实现具体策略:
为每个策略创建一个类,实现策略接口。这里我们就定义仨个,分别为策略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方法实现。然后,可以在运行时动态地选择使用哪个策略。
创建上下文类
- 创建上下文类:
由于客户端代码通常会有一个上下文(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
- 配置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实例。
使用策略
- 使用策略:
在你的应用中,你可以根据需要注入并使用不同的策略,说白了就是为了根据传入的策略名称执行相应的策略。实现代码如下:仅供参考
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框架中的一个应用示例。
测试策略
- 测试策略:
接着我们定义一个测试代码或者控制器中,调用服务方法并传入不同的策略名称来测试策略模式。这里我们就使用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传递。方法内部调用strategyService
的executeStrategy()
方法,并传入策略名称。方法返回一个字符串,格式为"Strategy executed: "加上策略名称。这个字符串将被自动序列化为JSON或其他格式的响应体,并发送给客户端。最后该接口请求返回值的是一个描述性字符串,它告诉客户端策略执行的结果。在实际应用中,你可能会返回更复杂的对象或数据结构,而不是简单的字符串。
通过上述步骤,你可以在Spring Boot应用中灵活地使用策略模式,根据用户请求或其他条件动态地改变算法行为。这种模式提高了代码的可扩展性和可维护性,并且可以根据需求轻松添加新的策略实现。
接口测试
- 接口测试:
接着,我们就根据如上定义的接口来进行一波本地测试,检验下是否都达到了预期目的,能够根据所传入的参数执行对应的策略;测试记录如下,仅供参考:
执行测试前,我们先重启项目,让我们刚写的代码都生效。然后检查下指定的环境及启动端口是多少:
启动项目成功的表现:
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天后未获授权禁止转载,侵权必究!