Spring实现策略模式

本文介绍了策略模式在Java中的应用,通过Spring和Java8的特性展示了两种不同的实现策略。第一种实现利用Spring的Aware接口,通过key获取不同的策略对象;第二种实现则借助lambda表达式,通过Function存储并动态调用策略方法。这两种方式分别适用于不同粒度的策略管理和技术场景。文章还提及了Spring的Aware接口在获取对象和环境信息中的作用。
摘要由CSDN通过智能技术生成

什么是策略模式

指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法
在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护
如我最近写的爬虫小说,行为是爬取小说内容,但是针对不同的网站,实现都不一样
本文利用spring和java的新特性,整理了策略模式的两种实现方式

本文收获

1.java8的lambda
2.spring的aware接口
3.策略模式

实现方式

方式一:

1. 定义接口和实现类,给每个不同的实现类指定 key

/**
 * 定义接口
 */
public interface TestProxy {

    public String getTestKey();

    public void operate(Map<String, String> param) throws IOException;

}
@Component
public class TestProxyImpl implements TestProxy {
    @Override
    public String getTestKey() {
        return "test1";
    }

    @Override
    public int[] operate(int[] arr) {
        System.out.println("我是快速排序算法");
        return arr;
    }
}
@Component
public class Test2ProxyImpl implements TestProxy {
    @Override
    public String getTestKey() {
        return "test2";
    }

    @Override
    public int[] operate(int[] arr) {
        System.out.println("我是选择排序算法");
        return arr;
    }
}

2. 实现 Aware 接口,并通过 map 关联存储 key 和策略对象

/**
 * 实现spring的Aware接口
 * 通过class获取对象
 */
@Component
public class TestFactory implements ApplicationContextAware {
    private Map<String, TestProxy> beanMap;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //获取指定接口的实现类
        Map<String, TestProxy> map = applicationContext.getBeansOfType(TestProxy.class);
        this.beanMap = new HashMap<>(map.size());
        map.forEach((k, v) -> this.beanMap.put(v.getBookEnum().name(), v));
    }

    /**
     * 通过策略key获取具体的对象
     */
    public <T extends TestProxy> T getTestProxy(String code) {
        return (T)this.beanMap.get(code);
    }
}

3. 通过 key 动态选择策略

    @GetMapping({"/testStrategy/{key}"})
    @ApiOperation(value = "测试接口", notes = "test")
    public void testStrategy(@PathVariable("key") String key) throws Exception {
        TestProxy testProxy = testFactory.getTestProxy(key);
        int[] arr = new int[]{5,1,2,3,4};
        int[] result = testProxy.operate(arr);
        System.out.println(result);
    }

方式二:

1. 定义策略

public interface ITestService {

    String method1(Map<String, String> map);

    String method2(Map<String, String> map);

    String method3(Map<String, String> map);

}

2. 通过 Function 函数存储策略

@Service
public class NewStrategy {

    @Autowired
    private ITestService iTestService;
    private static final Map<String, Function<Map<String, String>, String>> GRANT_TYPE_MAP =new HashMap<>();

    /**
     *  通过function初始化业务分派逻辑,代替了if-else部分
     *  key: 策略key
     *  value: 方法体
     */
    @PostConstruct
    public void newStrategy(){
        GRANT_TYPE_MAP.put("method1",v->iTestService.method1(v));
        GRANT_TYPE_MAP.put("method2",v->iTestService.method2(v));
        GRANT_TYPE_MAP.put("method3",v->iTestService.method3(v));
    }

    public static String getResult(String key, Map<String, String> param){
        //根据key获取具体的策略
        Function<Map<String, String>, String> result = GRANT_TYPE_MAP.get(key);
        if(result!=null){
            //传入参数执行方法体
            return result.apply(param);
        }
        return null;
    }

}

3. 通过 key 动态选择策略

    @PostMapping ({"/getResult/{type}"})
    @ApiOperation(value = "测试策略活动的新玩法", notes = "test")
    @ResponseBody
    public String getResult(@RequestBody Map<String, String> param, @PathVariable("type") String type) {
        return NewStrategy.getResult(type, param);
    }

两者区别

1. 细粒度不同,前者以对象为单位,每一个新的策略都需要定义 key 和实现接口,后者只需关注策略方法即可

2. 技术性不同,前者通过 spring 的 Aware 接口玩法实现,后者通过 java 的 lambda 函数式编程实现

题外话

Aware是spring系列一个比较常用的接口,用它可以实现一些方便的操作
如获取对象,获取当前环境

@Component
public class BeanFactory implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanFactory.context = applicationContext;
    }

    /**
     * 通过class获取对象
     */
    public static  <T> T getBean(Class<T> className) {
        return context.getBean(className);
    }

    /**
     * 获取当前项目环境
     */
    public static String getActiveProfile() {
        return context.getEnvironment().getActiveProfiles()[0];
    }
}


Python 系列:
读取文件 – 使用 python 读取 xls,xlsx,csv,doc,docx,pdf 格式的文件

阅读小工具 – 使用 python 开发无边框窗体阅读小工具

操作xlsx文件 – 使用 openpyxl 技术对 xlsx 的各种操作


前端系列:
扫雷游戏 – JavaScript 仿造 windows 编写 扫雷游戏

前端工具库 xlsx 处理表头合并 – 如何使用 xlsx 技术处理复杂的表头合并

CSS 布局技巧 – 对整体布局的心得体会

NVM Node 多版本控制教程 – Node 版本控制神器 NVM


Spring 系列:
Spring部署 – Spring 的多种 linux 部署方式

Spring实现策略模式 – 通过 Spring 实现多种策略模式

下面是一个使用Spring框架实现策略模式的示例: 首先,定义一个策略接 `Strategy`,包含一个 `execute()` 方法: ```java public interface Strategy { void execute(); } ``` 然后,创建几个具体的策略类实现该接口: ```java @Component public class StrategyA implements Strategy { @Override public void execute() { System.out.println("执行策略A"); } } @Component public class StrategyB implements Strategy { @Override public void execute() { System.out.println("执行策略B"); } } @Component public class StrategyC implements Strategy { @Override public void execute() { System.out.println("执行策略C"); } } ``` 接下来,创建一个策略上下文类 `StrategyContext`,并使用Spring的依赖注入功能将所有的策略类注入进来: ```java @Component public class StrategyContext { private final Map<String, Strategy> strategyMap; public StrategyContext(List<Strategy> strategies) { this.strategyMap = strategies.stream().collect(Collectors.toMap(Strategy::getClass.getSimpleName, Function.identity())); } public void executeStrategy(String strategyName) { Strategy strategy = strategyMap.get(strategyName); if (strategy != null) { strategy.execute(); } else { throw new IllegalArgumentException("Unsupported strategy: " + strategyName); } } } ``` 最后,在其他需要使用策略模式的地方,可以通过依赖注入 `StrategyContext` 对象,并调用其 `executeStrategy()` 方法执行相应的策略: ```java @Component public class SomeService { private final StrategyContext strategyContext; public SomeService(StrategyContext strategyContext) { this.strategyContext = strategyContext; } public void doSomething(String strategyName) { strategyContext.executeStrategy(strategyName); } } ``` 这样,通过使用Spring框架的依赖注入功能,我们可以方便地在运行时动态切换不同的策略实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值