当前位置:网站首页>Teach you how to kill if else
Teach you how to kill if else
2022-08-03 00:28:00 【horse crumbs】
今天想来跟大家讨论一下怎么干掉if else.
已经工作的人可能深有体会:没有什么是if else搞不掂的,如果有,那就再嵌套一层.
大多数人都是做业务开发的,if else是避免不了的,但怎么让if else的逻辑看起来更顺眼,变得更加好看,更加好维护呢?
如果之前看过三歪文章的同学可能就会想到「责任链模式」.
That's right, the chain of responsibility model
当你看到一个Service中有一大堆if else 逻辑的时候,可能你会幻想着要不要重构掉,但是始终下不了手.
所以,今天想来分享一个「通用」的责任链模式的模板,把if else给套进去就完事了,我相信都能学会.
之前写设计模式文章的时候,有的同学会评论说我把东西搞复杂了,本来就有简单的方式去弄,为啥就要嵌套这么多层去搞这些花里胡哨的东西.
在我看来,用最简单的方式去实现是没有任何问题的.但达到一定代码量的时候,多想想一下,换一个人去维护,人家能不能看懂,有没有更加好的方式,这往往就需要「抽象」的能力.
这也是为什么这么多人推崇设计模式的原因.
不多BB,来吧.
责任链通用实现
现在我就默认大家都知道什么是责任链模式了,如果还对这个不懂的同学,可以先看看我之前的文章.

首先,我们会有一个业务执行器接口,所有的业务实现都会实现该接口,这意味着上图的逻辑A、B、C都会实现这个接口
/**
* 业务执行器
* @author 三歪
*/
public interface BusinessProcess {
void process(ProcessContext context);
}
可以看到的是接口异常的简单,只有一个process处理的方法,方法接收的是ProcessContext
为什么process方法需要接收ProcessContext?很简单,我们在处理逻辑A、B、C的时候,可能逻辑B需要依赖逻辑A的处理结果.于是我们就需要有一个载体把这些给记录下来.
所以,我们就有了ProcessContext,它代表的是责任链的上下文.
/**
* 责任链上下文
* @author 3y
*/
public class ProcessContext {
// 标识责任链的code
private String code;
// 存储上下文的真正载体
private Model model;
// 责任链中断的标识
private Boolean needBreak = false;
}
现在责任链的执行器和责任链所涉及的上下文都已经有了,这意味着我们已经有了责任链最主要的抽象了.
接下来就是我们需要把链给串起来,于是我们需要一个模板,其实我们做的就是用一个List来把BusinessProcess的子类给串起来.
/**
* 业务执行模板(把责任链的逻辑串起来)
* @author 3y
*/
public class ProcessTemplate {
private List<BusinessProcess> processList;
public List<BusinessProcess> getProcessList() {
return processList;
}
public void setProcessList(List<BusinessProcess> processList) {
this.processList = processList;
}
}
OK,现在我们已经把责任链的整块给抽象好了,接下来就是暴露流程控制器去执行这个责任链:
/**
* 责任链的流程控制器(整个责任链的执行流程通用控制)
* @author 3y
*/
@Data
public class ProcessController {
// 不同的code 对应不同的责任链
private Map<String, ProcessTemplate> templateConfig = null;
public void process(ProcessContext context) {
//根据上下文的Code 执行不同的责任链
String businessCode = context.getCode();
ProcessTemplate processTemplate = templateConfig.get(businessCode);
List<BusinessProcess> actionList = processTemplate.getProcessList();
//遍历某个责任链的流程节点
for (BusinessProcess action : actionList) {
try {
action.process(context);
if (context.getNeedBreak()) {
break;
}
} catch (Exception e2) {
//...
}
}
}
}
我们可以看到的是在ProcessController执行链通用的流程控制器上会有一个Map去存储多个责任链的模板,这样做的好处就是:ProcessController这个流程控制器可以根据code支持多个责任链执行.
接下来就是我们有具体的BusinessProcess去加入到ProcessTemplate的链上,然后调用ProcessController的方法去执行整一条推送链.
一般我们在XML注入就好了,比如说现在我们有两个BusinessProcess的实现,分别是白名单和发消息的逻辑:
/**
* 白名单处理器
* @author 3y
*/
@Service
public class WhiteListProcess implements BusinessProcess {
@Override
public void process(ProcessContext context) {
UserModel user = (UserModel) context.getModel();
if ("3y".equals(user.getName())) {
context.setNeedBreak(true);
}
}
}
/**
* 发消息处理器
* @author 三歪
*/
@Service
public class SendMessageProcess implements BusinessProcess {
@Override
public void process(ProcessContext context) {
UserModel user = (UserModel) context.getModel();
System.out.println("给"+user.getName()+"发消息");
}
}
然后我们把上面两个处理器添加到ProcessTemplate的模板上,把ProcessTemplate添加到ProcessController的Map上:
<!--发送消息的责任链-->
<bean id="sendMessageTemplate" class="com.chainofresponsibility.ProcessTemplate">
<property name="processList">
<list>
<ref bean="whiteListProcess"></ref>
<ref bean="sendMessageProcess"></ref>
</list>
</property>
</bean>
<!--通用流程处理器,维护多条责任链-->
<bean id="processController" class="com.chainofresponsibility.ProcessController">
<property name="templateConfig">
<map>
<entry key="sendMessage" value-ref="sendMessageTemplate" />
</map>
</property>
</bean>
然后我们在接口里边执行这个责任链:
@RestController
public class UserController {
@Autowired
private ProcessController processController;
@RequestMapping("/send")
public void send(String userName) {
// 构建上下文
ProcessContext processContext = new ProcessContext();
UserModel userModel = new UserModel();
userModel.setAge("24");
userModel.setName(userName);
processContext.setModel(userModel);
processContext.setCode("sendMessage");
processController.process(processContext);
}
}
我做了这么大的一套东西实现了什么功能?其实就一个if逻辑:
if ("3y".equals(userModel.getName())) {
return;
}
System.out.println("给" + userModel.getName() + "发消息");
下面我们还是来看看效果,从功能上我们可以发现,只要我们输入的不是「3y」,那就会打印消息

上面的逻辑,实际上就是一套通用的责任链的代码,最核心的其实就是四个角色:「业务抽象接口」、「执行过程中的上下文」、「将业务实现类串起来」和「一个通用的控制器执行责任链」

如果没看懂的同学,三歪建议再对比一下代码看看,责任链这种设计模式是非常好用,在项目里边也是非常常见的.
只要把BusinessProcess/ProcessContext/ProcessTemplate/ProcessController的代码给拷过去自己的项目中,这就能帮你把原有的if else逻辑给干掉.
Pipeline
不知道大家看过Pipeline这个词了没,在学Redis的时候可能会见过,在Redis里边我们会用Pipeline去做批量的操作.
抛开Redis的Pipeline,但从宏观的角度上来,Pipeline其实是一种架构思想.
同时我也认为它是「责任链模式」的实现之一.
下面来看看我这边的一个Pipeline实现的架构图:

可以看到前人实现的Pipepline还是相对复杂的,没有上面通用的责任链模式好理解,经过分析可以看到都是换汤不换药的.
下次再见到Pipeline这个词的时候(因为这个词还是很常见的),你们就应该能想到责任链模式,然后你就发现你看懂了.
边栏推荐
猜你喜欢

【流媒体】推流与拉流简介

sre成长之路

典型相关分析CCA计算过程

Add and delete all these years, finally planted in MySQL architecture design!

Do you understand the factory pattern?

Byte's internal technical map is amazing and practical

Interviewer: can you talk about optimistic locking and pessimistic locks

如何抓住NFT、元|宇|宙新趋势?

终于明白:有了线程,为什么还要有协程?

Finally understand: With threads, why do we need coroutines?
随机推荐
测试ESP32-Zigbee转发命令 : 滑轨、继电器控制
golang刷leetcode:我能赢吗
源码构建LAMP环境-3
解道9-编程技术6
YAML文件格式
apache calcite中关于model文件配置
What is the core business model of the "advertising e-commerce" that has recently become popular in the circle of friends, and is the advertising revenue really reliable?
JS函数防抖&函数节流及其使用场景
HCIP--BGP基础实验
sre成长之路
最近火爆朋友圈的“广告电商”,核心商业模式是什么,广告收入真实靠谱吗?
Electrical diagram of power supply system
[Dry goods] Best practice of sub-library and sub-table
JumpServer开源堡垒机完成龙芯架构兼容性认证
如何抓住NFT、元|宇|宙新趋势?
【流媒体】推流与拉流简介
Flink-shell
人尽皆知的云原生,到底是大势所趋还是过度炒作?
Flink Yarn Per Job - 启动AM
面试官居然问我:删库后,除了跑路还能干什么?