首页 > 其他分享 >【转】SpringBoot实现策略模式

【转】SpringBoot实现策略模式

时间:2023-12-06 09:57:00浏览次数:22  
标签:execute return SpringBoot int 模式 class Override public 策略

文章来源: 微信公众号 《Java极客技术》  ,作者:鸭血粉丝Tang 

 

1. 普通代码实现

  在介绍 SpringBoot 中如何实现策略设计模式之前,我们先简单的回顾一下策略模式的设计思路。以编写一个简单的程序计算器,代码如下!

  首先,我们定义一个Operation接口,用于逻辑的计算

public interface Operation {

    /**
     * 执行计算
     * @param a
     * @param b
     * @return
     */
    int execute(int a, int b);
}

  接着,分别将四个if判断逻辑独立成一个模块,来单独处理

public class AddOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a + b;
    }
}
public class SubOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a - b;
    }
}
public class MultiOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a * b;
    }
}
public class DivOperation implements Operation {

    @Override
    public int execute(int a, int b) {
        return a / b;
    }
}

  然后,创建一个工厂类,用于处理客户端传入的参数

public class OperatorFactory {

    private static Map<String, Operation> operationMap = new HashMap<>();

    static {
        //初始化实现类
        operationMap.put("add", new AddOperation());
        operationMap.put("sub", new SubOperation());
        operationMap.put("multi", new MultiOperation());
        operationMap.put("div", new DivOperation());
        // more operators
    }

    /**
     * 获取对应的目标实现类
     * @param operator
     * @return
     */
    public static Optional<Operation> getOperation(String operator){
        return Optional.ofNullable(operationMap.get(operator));
    }

}

  最后,在需要的地方引入方法即可!

public class OperatorTestMain {

    public static void main(String[] args) {
        //获取计算的目标实现类
        Operation targetOperation = OperatorFactory
                .getOperation("add")
                .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
        int result = targetOperation.execute(1, 2);
        System.out.println("result:" +  result);
    }
}

  以上就是一个典型的策略模式的实践思路,从代码阅读性、扩展性角度看,还是非常干净利落的。

 

2. SpringBoot 实践应用

2.1 方案1

  首先,我们还是定义一个Command接口,用于方法的抽象和统一

public interface Command {

    /**
     * 命令类型
     * @return
     */
    String operateType();

    /**
     * 执行
     * @param a
     * @param b
     * @return
     */
    Integer execute(int a, int b);

}

  接着,编写四套不同的计算处理逻辑

@Component
public class AddCommand implements Command {

    @Override
    public String operateType() {
        return "add";
    }

    @Override
    public Integer execute(int a, int b) {
        return a + b;
    }
}
@Component
public class SubCommand implements Command {

    @Override
    public String operateType() {
        return "subtract";
    }

    @Override
    public Integer execute(int a, int b) {
        return a - b;
    }
}
@Component
public class MultiCommand implements Command {

    @Override
    public String operateType() {
        return "multiply";
    }

    @Override
    public Integer execute(int a, int b) {
        return a * b;
    }
}
@Component
public class DivCommand implements Command {

    @Override
    public String operateType() {
        return "divide";
    }

    @Override
    public Integer execute(int a, int b) {
        return a / b;
    }
}

  然后,编写一个类似于上文的策略处理类

@Component
public class CalculatorService implements ApplicationContextAware {

    private Map<String, Command> commandMap = new ConcurrentHashMap<>();

    /**
     * 执行计算
     * @param operateType
     * @param a
     * @param b
     * @return
     */
    public int calculate(String operateType,int a, int b){
        Command targetCommand = Optional.ofNullable(commandMap.get(operateType))
                .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
        return targetCommand.execute(a,b);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, Command> tempMap = applicationContext.getBeansOfType(Command.class);
        tempMap.values().forEach(source -> commandMap.put(source.operateType(), source));
    }

}

  最后,我们只需要在适当的位置应用即可!

@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

    @Autowired
    private CalculatorService calculatorService;

    @Test
    public void test(){
        int result = calculatorService.calculate("add", 1,2);
        System.out.println("result:" +  result);
    }
}

  总结:这种方案的实践,和上面介绍的思路基本上一致,不同的地方在于,当 Springboot 启动时,会将对象注入到IOC容器。

 

2.2 方案2(推荐)

  翻查Spring的ioc容器,你会发现一个秘密,当一个接口有多个实现类时,Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类。

  简单的说,我们只需要通过@Autowired注入对象,不需要通过CalculatorService这个类进行单独配置,操作方式如下!

  首先,编写一个CommandFactory工厂类,用于逻辑的处理

@Component
public class CommandFactory {

    /**
     * Spring会自动将Strategy接口的实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
     */
    @Autowired
    private Map<String, Command> commandMap;

    /**
     * 执行计算
     * @param operateType
     * @param a
     * @param b
     * @return
     */
    public int calculate(String operateType,int a, int b){
        Command targetCommand = Optional.ofNullable(commandMap.get(operateType))
                .orElseThrow(() -> new IllegalArgumentException("Invalid Operator"));
        return targetCommand.execute(a,b);
    }
}

  最后,直接在合适的地方使用CommandFactory即可!

@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

    @Autowired
    private CommandFactory commandFactory;

    @Test
    public void test(){
        int result = commandFactory.calculate("addCommand", 1,2);
        System.out.println("result:" +  result);
    }
}

  总结:方案二和方案一的不同点在于,不需要显式的编写CalculatorService策略处理类来初始化对象,Spring在初始化对象的时候,可以帮忙我们实现对象的注入!

 

3. 总结

  本文主要围绕在 SpringBoot 引入策略模式的设计思路和实践方法进行介绍,在实际的业务开发中,合理的使用策略模式,能让代码看起来更佳清爽,业务扩展性也更佳强大,希望能帮助到大家!

 

标签:execute,return,SpringBoot,int,模式,class,Override,public,策略
From: https://www.cnblogs.com/huanshilang/p/17878818.html

相关文章

  • go设计模式之工厂模式
    Go语言实现设计模式之工厂方法模式原创 汀风 汀风说后端 2023-12-0608:10 发表于北京汀风说后端编程知识普及,让学习与工作变得更简单。18篇原创内容公众号摘要:工厂方法模式是一种创建型设计模式,它将对象的创建延迟到子类中进行,通过定义一个创建对......
  • 使用分布式事务 Seata 的 TCC 模式
    Seata的TCC模式需要通过人工编码来实现数据的回滚恢复,有点麻烦,但是性能最高。TCC是3个方法的首字母缩写,即Try方法、Confirm方法、Cancel方法。Try方法进行资源的检查和冻结,Confirm方法是当所有事务都成功后调用的方法,Cancel方法是当整体事务中某个分支事务失败时调用......
  • sping_boot学习系列-搭建springboot项目工程
    搭建springboot工程方式一.通过idea SpringInitializr搭建详细步骤:1.创建一个新项目File->New->Project...2.项目环境配置选择SpringInitializr(20231205:注最低版本是jdk17,若搭建jdk8版本的,可先搭建jdk17版本的,修改pom.xml文件)默认即可,可修改项目名称选择maven......
  • 23种设计模式——抽象工厂模式
    今天我们来学习一下第三种设计模式——抽象工厂模式,概念:所谓抽象工厂模式就是提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类。它允许客户端使用抽象的接口来创建一组相关的产品,而不需要关心实际产出的具体产品是什么。这样一来,客户就可以从具体的产品中被......
  • VMware虚拟机nat模式路由器ping不通虚拟机为什么?
    在VMware虚拟机中,使用NAT(NetworkAddressTranslation)模式时,虚拟机会与虚拟的路由器连接,并通过该路由器与宿主机进行通信。因此,如果NAT模式下无法ping通虚拟机,可能有以下几个原因:路由器配置问题:检查虚拟路由器的网络配置,确保其能够正确地连接到宿主机和虚拟机,并且有正确的IP地址和......
  • 控制文件读写内容的模式
    控制文本读写格式t(默认的):文本模式读写都是以字符串的为单位的只能针对文本文件必须加入encoding参数b:二进制模式读写文件都是以bytes/二进制为单位可以针对所有的文件不可以加入encoding参数前提:b/t模式都不能单独使用,必须与r/w/a之一结合使用。(1)t模......
  • springboot @PostConstruct无效的解决
    springboot@PostConstruct无效的解决问题描述:在使用SpringBoot框架时,通过@PostConstruct注解修饰的方法可能会出现无法执行的情况。解决过程:1.确认依赖首先,我们需要确认在项目中是否引入了正确的依赖。在pom.xml文件中,需要引入spring-boot-starter-web包,这个包中含......
  • 控制文本读写内容的模式
    控制文本读写格式t(默认的):文本模式读写都是以字符串的为单位的只能针对文本文件必须加入encoding参数b:二进制模式读写文件都是以bytes/二进制为单位可以针对所有的文件不可以加入encoding参数前提:b/t模式都不能单独使用,必须与r/w/a之一结合使用。(1)t模......
  • springboot整合redis
    spring:redis:port:6379host:192.168.88.101password:111111lettuce:pool:max-active:8max-wait:-1msdatabase:0yml配置(单机版)spring:redis:password:111111lettuce:cluster:refr......
  • 基于SpringBoot实现文件的上传下载
    (一)概述文件上传下载一直都是一个系统最常用也是最基本的功能点,刚好最近公司的项目上有用到这个功能,于是自己就用SpringBoot也写了一个简化的版本,已实现文件的上传和下载功能。(二)创建项目首先创建一个SpringBoot的项目,接着引入相关的依赖,因为涉及到数据库的操作,所以依赖会比较......