1.写在前面
前段时间,和同事共同开发一个关于保险继续率的需求。简单来讲,就是根据数据库中的保单数据从省、公司、产品、人等不同维度计算继续率数据并落库。需求并不复杂,实现一开始想的就是定时任务去跑数,然后去根据不同维度做一个标识,去计算不同的数据,插入数据库。
当然,首当其冲想到的是策略模式。毕竟if else 或者是 switch 都感觉太冗余,而且并不好扩展。
2.代码实现
首先定义策略接口类
public interface Strategy {
/**
* 判断当前执行策略的具体实现类
*
* @return
*/
String getName();
/**
* 执行策略
*/
void excutor();
}
实现类A 、 B
@Service
public class StrategyA implements Strategy {
@Override
public String getName() {
return "strategyA";
}
@Override
public void excutor() {
System.out.println("strategyA");
}
}
@Service
public class StrategyB implements Strategy {
@Override
public String getName() {
return "strategyB";
}
@Override
public void excutor() {
System.out.println("strategyB");
}
}
这样在想要去调用策略的地方去通过注入map,然后直接去get使用就可以
// 注入
@Autowired
private Map<String,Strategy> strategyMap ;
......
// 使用
public void cusumer(Map<String,String> params){
// 省略校验和其他逻辑代码 ...
Strategy stg = strategyMap.get(params.get("flag"));
if(null != stg){
stg.execute();
}
}
这样虽然可以实现在实际调用的时候选到合适的策略类,但是只要是需要使用策略的时候,都需要注入这个map,显得比较麻烦,于是进行了改进。
@Component
public class StrategyMap {
public static Map<String, Strategy> MAP = new HashMap<>();
/**
* 可以通过这种对静态属性进行赋值
*
* @param list
*/
@Autowired
public void setPartnerService(List<Strategy> list) {
list.forEach(item -> MAP.put(item.getName(), item));
}
这样调用方可以直接通过
StrategyMap.MAP.get("strategyB").execute();
// 需要注意npe
去实现调用。
当然,我们可以将调用逻辑进行封装,让StrategyMap去承担调用,这样就不需要处处都去处理npe问题,代码如下
// StrategyMap 中增加方法
/**
* 执行
*
* @param name
*/
public static void excutor(String name) {
Optional.ofNullable(MAP.get(name)).ifPresent(item -> item.excutor());
}
......
// 调用端
StrategyMap.excutor("strategyB");
最后引入责任链模式:
// StrategyMap 中增加属性LIST
public static final List<Strategy> LIST = new ArrayList();
/**
* 责任链模式
*
* @param name
*/
public static void excutor2(String name) {
LIST.stream().filter(item -> item.getName().equals(name)).findFirst().get().excutor();
}
......
// 调用端
StrategyMap.excutor2("strategyB");