三歪手把手教你干掉if else

简介: 今天想来跟大家讨论一下怎么干掉if else。

今天想来跟大家讨论一下怎么干掉if else

已经工作的人可能深有体会:没有什么是if else搞不掂的,如果有,那就再嵌套一层。

大多数人都是做业务开发的,if else是避免不了的,但怎么让if else的逻辑看起来更顺眼,变得更加好看,更加好维护呢?

如果之前看过三歪文章的同学可能就会想到「责任链模式」。

没错就是 责任链模式

当你看到一个Service中有一大堆if else 逻辑的时候,可能你会幻想着要不要重构掉,但是始终下不了手。

所以,今天想来分享一个「通用」的责任链模式的模板,把if else给套进去就完事了,我相信都能学会

之前写设计模式文章的时候,有的同学会评论说我把东西搞复杂了,本来就有简单的方式去弄,为啥就要嵌套这么多层去搞这些花里胡哨的东西。

在我看来,用最简单的方式去实现是没有任何问题的。但达到一定代码量的时候,多想想一下,换一个人去维护,人家能不能看懂,有没有更加好的方式,这往往就需要「抽象」的能力。

这也是为什么这么多人推崇设计模式的原因。

不多BB,来吧。


责任链通用实现


现在我就默认大家都知道什么是责任链模式了,如果还对这个不懂的同学,可以先看看我之前的文章。

30.jpg

首先,我们会有一个业务执行器接口,所有的业务实现都会实现该接口,这意味着上图的逻辑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添加到ProcessControllerMap上:

<!--发送消息的责任链-->
<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」,那就会打印消息

31.jpg

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

32.jpg

如果没看懂的同学,三歪建议再对比一下代码看看,责任链这种设计模式是非常好用,在项目里边也是非常常见的。

只要把BusinessProcess/ProcessContext/ProcessTemplate/ProcessController的代码给拷过去自己的项目中,这就能帮你把原有的if else逻辑给干掉。


Pipeline


不知道大家看过Pipeline这个词了没,在学Redis的时候可能会见过,在Redis里边我们会用Pipeline去做批量的操作。

抛开Redis的Pipeline,但从宏观的角度上来,Pipeline其实是一种架构思想。

同时我也认为它是「责任链模式」的实现之一。

下面来看看我这边的一个Pipeline实现的架构图:

33.jpg

可以看到前人实现的Pipepline还是相对复杂的,没有上面通用的责任链模式好理解,经过分析可以看到都是换汤不换药的。

下次再见到Pipeline这个词的时候(因为这个词还是很常见的),你们就应该能想到责任链模式,然后你就发现你看懂了。

目录
相关文章
|
自然语言处理 机器学习/深度学习 Windows
Hanlp-地名识别调试方法详解
HanLP收词特别是实体比较多,因此特别容易造成误识别。下边举几个地名误识别的例子,需要指出的是,后边的机构名识别也以地名识别为基础,因此,如果地名识别不准确,也会导致机构名识别不准确。
1501 0
|
9天前
|
人工智能 自然语言处理 安全
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
本文聚焦阿里云2026年推出的三款自研AI办公产品,清晰拆解千问办公、Qoder Teams、Qoder CN的差异化定位与能力边界:千问办公主打职场全场景提效,支持自然语言指令一键完成PPT生成、数据分析等高频办公任务;Qoder Teams面向程序员团队,深度整合AI代码生成、团队协同与企业知识库能力;Qoder CN则专为金融、政务等强合规场景打造,实现数据不出境与VPC私有化部署。文章同步给出分场景选型指南与最新活动定价,帮助不同类型的企业按需组合产品,实现业务岗、研发岗与强合规场景的AI能力全覆盖。
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
|
21天前
|
人工智能 缓存 前端开发
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
DeepSeek Harness + DeepSeek V4 Pro 项目实战保姆级教程!手把手带你从零安装开源 AI 编程工具,开发架构图、知识讲解网站、3D 网页游戏、全栈 AI 应用 4 个项目,覆盖运行模式选择、插件安装与开发,看看能不能对标 Claude。
13316 91
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
|
14天前
|
Web App开发 人工智能 API
16 个超火的 DeepSeek Harness 插件,大肥鱼已经落后 N 个版本了。。。
DeepSeek Harness 精选插件推荐合集,从图片识别、浏览器操控、多 Agent 协作到手机远程控制,一口气带你看完 DSH 社区热门的十几个插件,覆盖技能扩展、UI 界面增强、整活玩法三大类,让你的鲸鱼变得更强。
1828 4
|
15天前
|
人工智能 Java BI
【AI】DeepSeek Harness 安装、运行、管理插件
本文介绍了如何运行DeepSeek开源的Agent框架DeepSeek Harness(dsh)。主要内容包括:使用nvm安装适配的Node版本;通过代理加速克隆GitHub源码;使用pnpm安装依赖并启动项目;配置DeepSeek API Token;安装扩展功能的插件。该框架自带Web界面,支持模型适配、文件编辑等插件化功能
2036 1
|
10天前
|
人工智能 Linux iOS开发
Ollama使用教程:Ollama官网下载、Ollama本地部署大模型(2026最新)
Ollama 是一款免费开源的本地大模型运行工具,支持在 Windows/macOS/Linux 上离线运行 Qwen、DeepSeek、Llama 等主流开源模型,数据不出本机、隐私安全。提供 OpenAI 兼容 API,命令行一键拉取/运行/管理模型,无需联网,无调用限制,是开发者与 AI 爱好者部署本地 AI 助手的理想选择。(239 字)
|
人工智能 JavaScript 开发工具
DeepSeek Harness 本地安装与使用指南
DeepSeek Harness(DSH)是DeepSeek AI开源的Agent运行框架,支持本地文件操作、命令执行与工具调用。基于Cordis插件架构,具备高扩展性与强可控性,适合开发者搭建可控Agent环境或开展模型基准测试。当前为开发者预览版,需Node.js环境,推荐先用`npx @deepseek-ai/dsh web`快速体验。
5293 0

热门文章

最新文章