• [Spring源码阅读]如何通过配置文件管理策略


    策略模式的基本结构

    策略,可以简单理解为解决某个问题的具体方法。

    当一个问题的解决方法有多种,并且需要根据具体场景灵活替换时,我们可以使用策略模式。

    策略模式的概念不多说,借网上的图来描述一下:

     策略的实现依赖于具体的业务场景,这个没什么好说的;但是策略的管理是一种比较通用的方式,也是本文探讨的主要内容。

    以上图为例,Context维护着策略的实现,executeState接口屏蔽了这种实现。除了提供获取策略的途径外,Context还需要做下面两件事:

    1. 策略收集。对于Context来说,策略交给他管理后,他需要知道一共有哪些策略。

    2. 策略配置。即当前生效的策略时哪一个。(或者给executeStrategy加个参数policyName,客户端直接传进来,可以参考下面的案例)

    在平时的开发过程中,如果我们使用Spring或者相关的容器框架,可以考虑把所有的策略放到容器中。所以策略管理,可以简单地实现为:将所有实现Stategy接口的类从容器中取出来,放入Context中。

    示例代码如下:

    策略接口

    1. public interface Strategy {
    2. int doOperation();
    3. }

    实现类

    1. @Component
    2. public class StrategyA implements Strategy{
    3. @Override
    4. public int doOperation() {
    5. return 1;
    6. }
    7. }
    1. @Component
    2. public class StrategyB implements Strategy{
    3. @Override
    4. public int doOperation() {
    5. return 2;
    6. }
    7. }

    Context

    1. @Component
    2. public class StrategyContext {
    3. @Autowired
    4. private ApplicationContext applicationContext;
    5. private Map<String, Strategy> strategyMap = new HashMap<>();
    6. @PostConstruct
    7. public void init() {
    8. Map<String, Strategy> impls = applicationContext.getBeansOfType(Strategy.class);
    9. for (String key : impls.keySet()) {
    10. strategyMap.put(key, impls.get(key));
    11. }
    12. }
    13. public Strategy get(String policyName) {
    14. return strategyMap.get(policyName);
    15. }
    16. }

    问题点

    上述方法的问题点在于,针对每一组策略的Context,都需通过硬编码的方式来管理。

    什么意思呢?一个项目中可能不止有一个策略。比如

    Strategy1策略有对应的实现StrategyA、StrategyB、StrategyC;

    Strategy2有对应的实现StrategyD、StrategyE、StrategyF。

    当需要做成策略的功能点很多时,这个时候就需要写很多个init方法,维护很多个strategyMapt,出现了很多的冗余代码。

    Spring是如何解决这个问题的

    我们以DispatchServlet为例

     DispatcherServlet初始化的时候,会调用initStrategies方法

     以HandlerMapping为例,通过getDefaultStrategies获取到HandlerMapping所有的实例

     getDefaultStrategies具体实现

     配置文件的全貌

    配置文件中的每一个键值对代表一个策略组。key是策略接口,value是策略实现的集合。

     后面逻辑就很清晰了,通过key(策略)获取到values(策略实现)后,创建对应的策略实现。

     如何实际运用

    上述案例中的key,value是对应策略的全路径。但对于我们开发者来说,在实际项目中不必照搬Spring的所有实现。

    比如key可以设置为策略组的名称,value设置为策略实现的名称。获取策略的时候也不用去创建策略,可以兼容之前的做法,直接通过名称去Spring容器中取。

    这种方式确实可以减少一些重复代码,但付出的代价是,每次获取策略的时候,需要额外提供一个策略组的名称。

    总体看来,只能说是有利有弊吧。但如果开发构建大型系统,策略组特别多的话,这种方式还是很有必要的。

  • 相关阅读:
    Microsoft Learn: Docker入门教程
    vue脚手架安装
    瑞萨RZ/G2L处理器详细测评
    【Java集合框架】23 ——TreeMap 类
    文件系统系列专题之 Btrfs
    为安卓编写Linux内核驱动程序
    论文速览 MobiCom 2023 | NeRF2 : Neural Radio-Frequency Radiance Fields
    c# --- 面向对象之类与对象
    Ubuntu系统初始设置
    链表算法题
  • 原文地址:https://blog.csdn.net/qq_37855749/article/details/126455788