ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

实战讲解,原来是用 SpringBoot 实现策略模式可以这么简单

2022-06-19 00:04:01  阅读:148  来源: 互联网

标签:实战 execute return SpringBoot int class 讲解 Override public


一、介绍

一说起策略设计模式,相比大家都不陌生,在实际的业务开发中,合理的使用设计模式来编程,可以让代码阅读起来层次感更强,同时扩展性也会得到提升!

最近看同事的代码时候,学到了一个小技巧,在某些场景下合理的使用策略模式还是非常有用的,在此分享一下给大家。

二、代码实践

在介绍 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);
    }
}

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

那么,在SpringBoot项目中,我们应该如何使用呢?

三、SpringBoot 实践应用

3.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容器。

3.2、方案二(推荐)

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

简单的说,我们只需要通过@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在初始化对象的时候,可以帮忙我们实现对象的注入!

四、小结

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

来源:https://mp.weixin.qq.com/s/nAv2aKE-YnBZB3FN6I65OQ

标签:实战,execute,return,SpringBoot,int,class,讲解,Override,public
来源: https://www.cnblogs.com/konglxblog/p/16389629.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有