在使用策略模式时,我想小伙伴们经常有这样的不满,我的业务逻辑就3 4 行,你给我整一大堆类定义?有必要这么麻烦吗?我看具体的业务逻辑还需要去不同的类中,简单点行不行。
其实我们所不满的就是策略模式带来的缺点:1、策略类会增多 2、业务逻辑分散到各个实现类中,而且没有一个地方可以俯视整个业务逻辑
针对传统策略模式的缺点,在这分享一个实现思路,这个思路已经帮我解决了多个复杂if else的业务场景,理解上比较容易,代码上需要用到Java8的特性——利用Map与函数式接口来实现。
策略方法调用类,业务代码中注入此类调用doTask()方法,传入相关参数即可
package com.zwb.blog.admin.test;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
@RequiredArgsConstructor
@Slf4j
public class TestLambdaContext {
/**
* 封装策略方法 key:策略名称 value:对应策略方法
* Function<泛型1,泛型2> 泛型1:function.apply()方法的入参类型,同时也是策略方法的入参类型 泛型2:function.apply()方法的返参类型,同时也是策略方法的返参类型
* 可根据不同业务场景使用不同的函数式接口 如 UnaryOperator Consumer Predicate等 参考网址:https://www.runoob.com/java/java8-functional-interfaces.html
*/
private static final Map<String, Function<Object, Object>> map = new HashMap<>();
/**
* 此处采用构造注入,可替换为其他注入方式
*/
private final @NotNull TestLambdaStrategy testLambdaStrategy;
/**
* 初始化策略map对象
*/
@PostConstruct
public void init() {
map.put("策略名称一", testLambdaStrategy::testOne);
map.put("策略名称二", testLambdaStrategy::testTwo);
map.put("策略名称三", testLambdaStrategy::testThree);
map.put("策略名称四", testLambdaStrategy::testFour);
}
/**
* 根据入参key从map中获取不同的策略方法执行
*
* @param key 策略名称
* @param param 策略方法所需入参
* @return
*/
public static Object doTask(String key, Object param) {
//根据key从map中获取对应的策略方法
Function<Object, Object> function = map.get(key);
if (function != null) {
//传入策略方法所需参数,执行对应的策略方法
return function.apply(param);
}
return null;
}
}
策略方法类,该类中一个方法对应一个策略
package com.zwb.blog.admin.test;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
@Slf4j
public class TestLambdaStrategy {
public Object testOne(Object s) {
//执行业务方法......
return "策略模式1,接受参数为:" + s;
}
public Object testTwo(Object s) {
//执行业务方法......
return "策略模式2,接受参数为:" + s;
}
public Object testThree(Object s) {
//执行业务方法......
return "策略模式3,接受参数为:" + s;
}
public Object testFour(Object s) {
//执行业务方法......
return "策略模式4,接受参数为:" + s;
}
}
模拟调用
package com.zwb.blog.admin.test;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/blogs/test")
public class TestController {
@GetMapping("/testMethod")
public void testMethod() {
String doTask = (String) TestLambdaContext.doTask("策略名称一", "123");
System.out.println(doTask);
doTask = (String) TestLambdaContext.doTask("策略名称二", "456");
System.out.println(doTask);
doTask = (String) TestLambdaContext.doTask("策略名称三", "789");
System.out.println(doTask);
doTask = (String) TestLambdaContext.doTask("策略名称四", "10 11 12");
System.out.println(doTask);
}
}
输出结果