设计模式第1篇 | 责任链模式

🚀 作者简介:程序员小豪,全栈工程师,热爱编程,曾就职于蔚来、腾讯,现就职于某互联网大厂,技术栈:Vue、React、Python、Java

引言

hello,大家好,我是程序员小豪,本期博客我们来学习一下责任链模式,大家在工作中应该都遇到过这样一种场景:出差申请,通常出差申请的要求都是比较严格的,因为现在部门都在控制预算,小豪所在的公司呢,出差申请需要经过三层审批,先经过组长审批,组长审批通过再到总监审批,总监审批通过再到部门经理审批,这一整个审批环节只有有一环没有通过都不会走到下一个环节的审批,像这种需要顺序执行,后一个环节的执行需要依赖前一个环节的结果状态的场景就很适合使用责任链模式。

实现

不用责任链模式的代码

这是我在网上看到有的同学是这样实现上面的场景的,整个代码的if else嵌套过多过深,整个代码变得比较复杂,虽然这段代码只有3个if else,但是实际业务场景会更复杂,如果有新人进入团队熟悉这段代码,阅读起来难度会比较高,也很难维护,很难拓展

javascript 复制代码
function examine() {
  // 组长审批通过
  if(isLdOk) {
    console.log('小豪的出差申请组长审批通过');

    // 总监审批
    directorExamine()

    // 总监审批通过
    if(isDireactorOk) {
      console.log('小豪的出差申请总监审批通过');

      // 部门经理审批
      managerExamine()

      // 部门经理审批通过
      if(isManagerOk) {
        console.log('小豪的出差申请部门经理审批通过,全部通过完毕');
      } else {
        console.log('小豪的出差申请被部门经理驳回');
      }

    } else {
      console.log('小豪的出差申请被总监驳回');
    }

  } else {
    console.log('小豪的出差申请被组长驳回');
  }
}

实现使用责任链模式的代码

接下来我将使用责任链模式来实现这一场景

javascript 复制代码
class Task {
  constructor(name, status, weight, next) {
    this.taskName = name;
    this.taskStatus = status;
    this.taskWeight = weight;
    this.nextTask = next;
  }
  setNext(next) {
    return (this.nextTask = next);
  }
  handle(weight) {
    // 0-审批不通过 1-审批通过
    this.taskStatus = this.taskWeight < weight ? 1 : 0;
    if (!this.taskStatus) {
      console.log(`${this.taskName}不通过`);
      return;
    }
    console.log(`${this.taskName}通过`);
    if(this.nextTask) {
        this.nextTask.handle(weight);
    } else {
        console.log('全部审批通过🎉');
    }
    
  }
}

const tasks = [
  { name: "组长审批", status: -1, weight: 1 },
  { name: "总监审批", status: -1, weight: 3 },
  { name: "部门经理审批", status: -1, weight: 5 },
];

let taskHeader
let taskHandle

for(let i = 0; i < tasks.length; i++) {
    let task = tasks[i]
    if(i === 0) {
        taskHeader = new Task(task.name, task.status, task.weight, null)
        taskHandle = taskHeader
    } else {
        taskHandle = taskHandle.setNext(new Task(task.name, task.status, task.weight, null))
    }
}

taskHeader.handle(10)

// 输出
// 组长审批通过
// 总监审批通过
// 部门经理审批通过
// 全部审批通过🎉

上面我实现了一个task类,这个task类是审批流程的每一个单元环节的抽象类,我们可以使用每一个环节的数据实例化一个task对象,其中task对象的nextTask属性是用来串联当前环节任务与下一个环节任务,他会被赋值为下一个环节的task实例化对象,taskWeight属性是权重,这里用权重的对比模拟领导审批时判断是否要给你的出差申请通过的判断。

下面的tasks数组是审批流程每一个环节的数据,我们遍历这个数组,将每一个环节都实例化为一个task对象,并且用nextTask属性串联当前环节和下一个环节

taskHeader是第一个环节task对象,最后taskHeader执行handle方法,并传入出差申请权重10,handle方法回去对比当前环节任务权重与出差申请的权重来判断是否审批通过,如果不通过将直接return不往下个环节流转,如果通过,判断是否还有下一个环节,有下一个环节就执行下一个环节的handle方法,没有下一个环节说明全部审批通过。

优点

通过上面两份代码的对比,我们可以总结出责任链模式的优点

  • 降低耦合度。它将请求的发送者和接收者解耦
  • 遵守单一职责原则,每一个环节只需要关心自己的逻辑
  • 可拓展性、可维护性高

其他应用场景

  • express的中间件
  • 事件处理机制:在浏览器中,事件处理机制就是一个典型的责任链模式的应用。当事件发生时,它会从目标元素开始沿着 DOM 树向上传播,每个元素都有机会处理该事件。如果某个元素无法处理事件,它会将事件传递给它的父级元素,直到找到能够处理事件的元素或者事件冒泡至根元素。
  • 多重表单校验

结语

各位看官老爷们好,小豪已经建立了技术交流群,如果你很感兴趣,可以私信我加入我的社群。

📝社群中不定时会有很多活动,例如学习资料分享、大厂面经分享、技术讨论、行业大佬创业杂谈等等。

📝本人目前是在互联网大厂正式工作,也有过多个大厂的工作经历,加入社群也会有简历修改辅导,模拟面试,手把手项目实战教学,大厂工作内推机会以及大厂面试题解析分享等福利。

📝社群方向很多,相关领域有Web全栈(前后端)、人工智能、AIGC、自媒体变现、前沿科技文章分享、论文精读等等。

📝不管你是多新手的小白,都欢迎你加入社群中讨论、聊天、分享,加速助力你成为下一个技术大佬!也随时欢迎您跟我沟通,一起交流,一起成长。变现、进步、技术、资料、项目、你想要的这里都会有

📝网络的风口只会越来越大,风浪越大,鱼越贵!欢迎您加入社群~一个人可以或许可以走的很快,但一群人将走的更远!

📝想都是问题,做都是答案!行动起来吧!欢迎评论区or后台与我沟通交流,也欢迎您扫描下方二维码直接加入到我的交流社群!(微信:adcoderhao)

相关推荐
爱的叹息10 分钟前
【前端】基于 Promise 的 HTTP 客户端工具Axios 详解
前端·网络·网络协议·http
遗憾随她而去.17 分钟前
从 0 开始认识 WebSocket:前端实时通信的利器!
前端·websocket·网络协议
摘星编程21 分钟前
并发设计模式实战系列(7):Thread Local Storage (TLS)
设计模式·并发编程
老兵发新帖1 小时前
pnpm常见报错解决办法
前端
Sonetto19991 小时前
Nginx 反向代理,啥是“反向代理“啊,为啥叫“反向“代理?而不叫“正向”代理?它能干哈?
运维·前端·nginx
沐土Arvin1 小时前
理解npm的工作原理:优化你的项目依赖管理流程
开发语言·前端·javascript·设计模式·npm·node.js
好_快1 小时前
Lodash源码阅读-baseUniq
前端·javascript·源码阅读
不秃的开发媛1 小时前
前端技术Ajax入门
java·开发语言·前端
牧羊狼的狼1 小时前
React.memo 和 useMemo
前端·javascript·react.js
xixixin_1 小时前
【uniapp】vue2 搜索文字高亮显示
java·服务器·前端·uni-app·交互·文字高亮