推荐关注
以下文章来源Java后端栈,回复”面试“获面试宝典
哈喽,各位新来的小伙伴们,大家好!由于公众号做了改版,为了保证公众号的资源能准时推送到你手里,大家记得将后端君的公众号 加星标置顶 ,在此真诚的表示感谢~
来源:blog.csdn.net/qq_44384533/article/details/109197926
上一篇:Docker 大势已去,Podman 即将崛起
正文
大家好,我是栈哥。
本文介绍策略模式的具体应用以及Map+函数式接口如何 “更完美” 的解决 if-else的问题。
最近写了一个服务:根据优惠券的类型resourceType和编码resourceId来 查询 发放方式grantType和领取规则
优惠券有多种类型,分别对应了不同的数据库表:
实际的优惠券远不止这些,这个需求是要我们写一个业务分派的逻辑
第一个能想到的思路就是if-else或者switch case:
switch(resourceType){ case "红包": 查询红包的派发方式 break; case "购物券": 查询购物券的派发方式 break; case "QQ会员" : break; case "外卖会员" : break; ...... default : logger.info("查找不到该优惠券类型resourceType以及对应的派发方式"); break;}
如果要这么写的话, 一个方法的代码可就太长了,影响了可读性。(别看着上面case里面只有一句话,但实际情况是有很多行的)
而且由于 整个 if-else的代码有很多行,也不方便修改,可维护性低。
策略模式是把 if语句里面的逻辑抽出来写成一个类,如果要修改某个逻辑的话,仅修改一个具体的实现类的逻辑即可,可维护性会好不少。关注编程技术圈
以下是策略模式的具体结构
策略模式在业务逻辑分派的时候还是if-else,只是说比第一种思路的if-else 更好维护一点。
switch(resourceType){ case "红包": String grantType=new Context(new RedPaper()).ContextInterface(); break; case "购物券": String grantType=new Context(new Shopping()).ContextInterface(); break; ...... default : logger.info("查找不到该优惠券类型resourceType以及对应的派发方式"); break;
但缺点也明显:
用上了Java8的新特性lambda表达式
这样子写的好处是非常直观,能直接看到判断条件对应的业务逻辑
需求:根据优惠券(资源)类型resourceType和编码resourceId查询派发方式grantType
上代码:
@Servicepublic 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("红包",resourceId->grantTypeSerive.redPaper(resourceId)); grantTypeMap.put("购物券",resourceId->grantTypeSerive.shopping(resourceId)); grantTypeMap.put("qq会员",resourceId->grantTypeSerive.QQVip(resourceId)); } public String getResult(String resourceType){ //Controller根据 优惠券类型resourceType、编码resourceId 去查询 发放方式grantType Function<String,String> result=getGrantTypeMap.get(resourceType); if(result!=null){ //传入resourceId 执行这段表达式获得String型的grantType return result.apply(resourceId); } return "查询不到该优惠券的发放方式"; }}
如果单个 if 语句块的业务逻辑有很多行的话,我们可以把这些 业务操作抽出来,写成一个单独的Service,即:
//具体的逻辑操作@Servicepublic class GrantTypeSerive { public String redPaper(String resourceId){ //红包的发放方式 return "每周末9点发放"; } public String shopping(String resourceId){ //购物券的发放方式 return "每周三9点发放"; } public String QQVip(String resourceId){ //qq会员的发放方式 return "每周一0点开始秒杀"; }}
入参String resourceId是用来查数据库的,这里简化了,传参之后不做处理。
用http调用的结果:
@RestControllerpublic class GrantTypeController { @Autowired private QueryGrantTypeService queryGrantTypeService; @PostMapping("/grantType") public String test(String resourceName){ return queryGrantTypeService.getResult(resourceName); }}
用Map+函数式接口也有弊端:
策略模式通过接口、实现类、逻辑分派来完成,把 if语句块的逻辑抽出来写成一个类,更好维护。
Map+函数式接口通过Map.get(key)来代替 if-else的业务分派,能够避免策略模式带来的类增多、难以俯视整个业务逻辑的问题。
最后给读者整理了一份BAT大厂面试真题,需要的可扫码加微信备注:“面试”获取。
◆ ◆ ◆ ◆ ◆
字节跳动面试经验总结,已顺利拿到offer!
一款神仙接私活低代码平台,吊到不行(附源码)
IntelliJ IDEA这样配置,代码效率嗖嗖的~
Intellij IDEA 2021.2.3 最新版免费激活教程(可激活至 2099 年,亲测有效)
分享一个牛逼的 Java 开源后台管理系统,不要造轮子了!
硬核!一套基于SpringBoot + Vue 的开源物联网智能家居系统(附源码)!
基于 SpringBoot2 + MybatisPlus 的商城管理系统(附源码)
重磅推荐:一套开源的网校系统,无论是自建网校还是接副业都很方便
前后端分离的接口规范
扒了一下西安一码通的接口,这特么不崩才怪呢~
两次绩效被打3.25B,员工将支付宝告上了法院,判了
西安一码通又崩了,官方回应!
欢迎添加栈哥个人微信 ysle007 进粉丝群或围观朋友圈
扫码关注带你吊爆Java后端技术
文章有问题?点此查看未经处理的缓存