本文介绍策略模式的具体应用以及Map+函数式接口如何 “更完美” 的解决 if-else的问题。
最近写了一个服务,根据挂号的类型regType以及编码regId来查询 排队规则arriveType
实现方式
- 根据挂号类型regType确定查询那张表
- 根据编码regId到对应的数据表里查询排队的规则
挂号有很多中类型,分别对应不同的数据表:
- 规则–>排队规则表
- GOV_VIP
- MER_VIP
- NOMORAM
这个需求需要我们写一个业务分派的规则逻辑
第一个能想到的思路就是if-else或者switch case:
switch(regType){
case "GOV_VIP":
查询GOV_VIP的排队规则
break;
case "MER_VIP":
查询MER_VIP的排队规则
break;
case "NOMORAM" :
查询NOMORAM的排队规则
break;
default : logger.info("查找不到对应规则");
break;
}
如果要这么写的话, 一个方法的代码可就太长了,影响了可读性。(别看着上面case里面只有一句话,但实际情况是有很多行的)
而且由于 整个 if-else的代码有很多行,也不方便修改,可维护性低。
Map+函数式接口
用上了Java8的新特性lambda表达式
- 判断条件放在key中
- 对应的业务逻辑放在value中
这样子写的好处是非常直观,能直接看到判断条件对应的业务逻辑
上代码:
@Service
public class QueryGrantTypeService {
@Autowired
private GrantTypeSerive grantTypeSerive;
private Map<String, Function<String,String>> grantTypeMap=new HashMap<>();
/**
* 初始化业务分派逻辑,代替了if-else部分
* key: 挂号类型
* value: lambda表达式,最终会获得该类型的排队方式
*/
@PostConstruct
public void dispatcherInit(){
grantTypeMap.put("GOV_VIP",regId->grantTypeSerive.getGov(resourceId));
grantTypeMap.put("MER_VIP",regId->grantTypeSerive.getMER(resourceId));
grantTypeMap.put("NOMORAM",regId->grantTypeSerive.getNOMORAM(resourceId));
}
public String getResult(String resourceType){
//Controller根据 排队类型redType、编码regId 去查询 排队方式
Function<String,String> result=getGrantTypeMap.get(regType);
if(result!=null){
//传入regId 执行这段表达式获得String型的grantType
return result.apply(regId);
}
return "查询不到该挂号类型的排队方式";
}
}
用http调用:
@RestController
public class GrantTypeController {
@Autowired
private QueryGrantTypeService queryGrantTypeService;
@PostMapping("/regType")
public String test(String regType){
return queryGrantTypeService.getResult(regType);
}
}
总结
策略模式通过接口、实现类、逻辑分派来完成,把 if语句块的逻辑抽出来写成一个类,更好维护。
Map+函数式接口通过Map.get(key)来代替 if-else的业务分派,能够避免策略模式带来的类增多、难以俯视整个业务逻辑的问题。