一文搞懂设计模式之责任链模式

大家好,我是晴天。我们又见面了,本周我们继续学习设计模式,本周将同大家一起学习责任链模式。

本文目录

场景引入

我们回想一下自己曾经经历过的考学场景,我们是如何一步一步考上大学的(为了简化过程只提取核心环节)。第一步,我们需要报名考试,第二步,我们需要去参加考试,第三步,我们才能够通过考试,顺利进入大学。这三个步骤必须要串行化执行,只有前一步通过了,我们才能进行后续的步骤,如果前一步没有通过,则提前终止整过流程,无需进行后续步骤了。
场景流程图

什么是责任链模式

责任链类图

责任链设计模式是一种行为型设计模式,它要求完成一件事情必须按照指定顺序进行,前一个环节完成了才能进行下一个环节,否则就提前终止。每个环节可以理解成一个链表的节点,当这个节点接收到上一个节点传送过来的信息时,开始进行自身的逻辑处理,处理完成后,传递给下一个节点,调用下一个节点的处理方法,直到链表遍历完成为止。

为什么需要责任链模式

责任链设计模式是一种行为型设计模式,它主要用于将请求沿着处理链传递,直到有一个处理者能够处理该请求为止。责任链模式有助于降低发送者和接收者之间的耦合度,使系统更加灵活和可扩展。

代码实战

实现顺序执行逻辑有两种处理方法,一种遍历方式,是将处理方法放到数组中,遍历处理方法即可,第二种就是使用责任链模式来处理。我们依次来看一下这两种实现方式。

遍历方式

package mainimport ("context""errors""fmt"
)type Student1 struct {Name     stringSignUp   bool // 是否考试报名TakeTest bool // 是否参加考试PassExam bool // 是否通过考试
}type handler1 func(ctx context.Context, stu *Student1) error// 报名考试
func SignUp1(ctx context.Context, stu *Student1) error {if stu.SignUp {fmt.Println(stu.Name + "已经报名了考试")return errors.New(stu.Name + "已经报名了考试了")}stu.SignUp = truefmt.Println(stu.Name + "正在进行考试报名")return nil
}// 参加考试
func TakeTest1(ctx context.Context, stu *Student1) error {if stu.TakeTest {fmt.Println(stu.Name + "已经参加了考试")return errors.New(stu.Name + "已经参加过考试了")}stu.TakeTest = truefmt.Println(stu.Name + "正在参加考试")return nil
}// 通过考试
func PassExam1(ctx context.Context, stu *Student1) error {if stu.PassExam {fmt.Println(stu.Name + "已经通过了考试")return errors.New(stu.Name + "已经通过了考试")}stu.PassExam = truefmt.Println(stu.Name + "通过了考试")return nil
}func main() {var handlers = []handler1{SignUp1, TakeTest1, PassExam1}var student = &Student1{Name: "张三",}for _, handler := range handlers {if err := handler(context.Background(), student); err != nil {fmt.Println(err)}}
}// 输出:
张三正在进行考试报名
张三正在参加考试
张三通过了考试

代码解释

上述代码定义了三个方法,分别是报名考试(SignUp1)、参加考试(TakeTest)和通过考试(PassExam),这三种方法按照顺序,组成处理方法数组,依次对Student1进行处理,如果某个方法已经判断状态为 true 了,则说明该环节已经参与过了,不需要再进行后续环节的处理了。

责任链模式

package mainimport "fmt"// 责任链模式
/*定义学生考学场景:step1:报名考试step2:参加考试step3:通过考试
*/// 学生
type Student struct {Name     stringSignUp   bool // 报名考试TakeTest bool // 参加考试PassExam bool // 通过考试
}type Section interface {Do(s *Student)           // 参与改环节setNext(section Section) // 设置下一个环节
}// 学生报名考试
type SignUp struct {next Section
}func (s *SignUp) Do(stu *Student) {if stu.SignUp {fmt.Println(stu.Name + "报名考试成功")s.next.Do(stu)return}stu.SignUp = truefmt.Println(stu.Name + "考生正在报名...")s.next.Do(stu)return
}func (s *SignUp) setNext(section Section) {s.next = section
}// 学生参加考试
type TakeTest struct {next Section
}func (p *TakeTest) Do(stu *Student) {if stu.TakeTest {fmt.Println(stu.Name + "参加考试")p.next.Do(stu)return}stu.TakeTest = truefmt.Println(stu.Name + "考生参加考试...")p.next.Do(stu)return
}func (p *TakeTest) setNext(section Section) {p.next = section
}// 学生通过考试
// 责任链最后一个节点,不需要请求后续节点的 Do 方法了
type PassExam struct {next Section
}func (p *PassExam) Do(stu *Student) {if stu.PassExam {fmt.Println(stu.Name + "通过考试成功")return}stu.PassExam = truefmt.Println(stu.Name + "通过考试...")return
}func (p *PassExam) setNext(section Section) {p.next = section
}func main() {var student = &Student{Name:     "张三",SignUp:   false,TakeTest: false,PassExam: false,}// 最后一个节点var pe = &PassExam{}// 倒数第二个节点var pt = &TakeTest{}// 倒数第三个节点var su = &SignUp{}// 把责任链的节点连接起来pt.setNext(pe)su.setNext(pt)// 调用责任链的首个节点的执行方法su.Do(student)
}

代码解释

上述代码实现了一个具有三个节点的责任链,三个节点分别是SignUp(报名考试)、TakeTest(参加考试)、PassExam(通过考试),每个责任链的节点都是一个 Section 类型,每个节点都实现了两个方法,一个是执行自身逻辑的 Do 方法,另一个就是连接下一个节点的 setNext 方法。这里注意,最后一个节点 PassExam 不需要调用下一个节点了(已经是最后一个节点了)。

两种处理方式的对比

遍历方式优点

  1. 遍历方式结构简单,能够方便地将处理方法按照指定顺序,对请求进行处理。

遍历方式缺点

  1. 每个处理方法之间没有必然的联系,无法通过上一个处理方法找到写一个处理方法,关联性不强。

责任链模式优点

  1. 节点之间相互串联,关联性比较强,当前节点可以根据自身节点的处理结果来决定是否将请求继续向下传递。
  2. 执行一整条责任链的逻辑处理,只需要调用头节点处理方法即可,就像是只调用了一个节点的处理方法一样。

总结

本文,我们介绍了什么是责任链模式,为什么需要责任链模式,遍历方式和责任链模式的使用方法,并且对比了遍历方式和责任链模式的优缺点。希望各位读者小伙伴能有些许收获。

写在最后

感谢大家的阅读,晴天将继续努力,分享更多有趣且实用的主题,如有错误和纰漏,欢迎留言给予指正。 更多文章敬请关注作者个人公众号 晴天码字。 我们下期不见不散,to be continued…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/208491.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fiddler抓包工具之fiddler的命令行窗口用法

fiddler的命令行窗口的相关命令 在fiddler官网有QuickExec使用教程,地址是QuickExec Reference - Fiddler Classic QuickExec 命令行窗口位于fiddler左下角黑色输入框,如下图: 按ALT Q,将焦点快速设置到QuickExec框。如果Fiddl…

代码随想录第二十二天(一刷C语言)|组合总数电话号码的字母组合

创作目的:为了方便自己后续复习重点,以及养成写博客的习惯。 一、组合总数 思路:参考carl文档和视频 1、需要一维数组path来存放符合条件的结果,二维数组result来存放结果集。 2、targetSum 目标和,也就是题目中的…

Python语言学习笔记之七(JOSN应用)

本课程对于有其它语言基础的开发人员可以参考和学习,同时也是记录下来,为个人学习使用,文档中有此不当之处,请谅解。 1、认识Json JSON (JavaScript Obiect Notation)是一种轻量级的数据交换格式,它是ECMAScript的一…

电源需要考虑的因素

做产品的都离不开电源,产品出问题也首先检查供电是否正常。今天给大家分享的是做好一个电源需要考虑哪些因素。 一. 描述输入电压影响输出电压几个指标形式 1. 稳压系数 A.稳压系数:表示负载不变时,稳压电源…

爬虫学习-基础(HTTP原理)

目录 一、URL和URI 二、HTTP和HTTPS (1)HTTP (2)HTTPS (3)HTTP与HTTPS区别 (4)HTTPS对HTTP的改进:双问的身份认证 三、TCP协议 (1)TCP三次握手…

vue项目node-sass^4.14.1 python gyp 报错解决办法

npm i node-sass4.14.1 --sass_binary_sitehttps://npm.taobao.org/mirrors/node-sass/参考链接:链接

浅析 TLS(ECDHE)协议的握手流程(图解)

浅析 TLS(ECDHE)协议的握手流程(图解) 通过 wireshark 抓取 HTTPS 包,理解 TLS 1.2 安全通信协议的握手流程。 重点理解几个点: TLS 握手流程:通过 wireshark 抓取 HTTPS 包理解。协商加密&a…

一文解决msxml3.dll文件缺失问题,快速修复msxml3.dll

在了解问题之前,我们必须首先清楚msxml3.dll到底是什么。DLL(Dynamic Link Libraries)文件是Windows操作系统使用的一个重要组成部分,用于存储执行特定操作或任务的代码和数据。msxml3.dll为Windows系统提供处理XML文档的功能。如…

文件上传---阿里云OSS

1.注册阿里云账户(注册完成后需要实名认证) 2.注册完账号之后,就可以登录阿里云 3. 创建bucket 4.创建 AccesskeyId 选择自己的开发语言 5. 阿里云Oss工具类 package com.sky.utils;import com.aliyun.oss.ClientException; import com.ali…

Redis缓存的使用

什么是缓存 缓存就是数据交换的缓冲区,是存储数据的临时地方,一般读写性能较高。 缓存的作用: 降低后端负载提高读写效率,降低响应时间 缓存的成本: 数据一致性成本代码维护成本运维成本 Redis特点 键值型数据库…

Upsert 及冲突(GORM)

GORM支持了数据库的upsert操作 upsert操作对于插入一条数据而言的,如果插入数据之前,没有这条数据,则会插入该条数据;如果插入数据之前就存在这条数据(索引值),就更新这条记录。 创建结构体 …

基于景区智慧灯杆、智能指路牌基础设施的景区建设应用

智慧景区是指运用现代信息技术手段,将景区内的资源、服务、管理等进行数字化、网络化和智能化整合,打造出高效便捷、安全舒适、互动体验和可持续发展的景区。智慧景区可以从以下几个方面进行体现: 智慧导览:通过使用智能化的导览…

vue 解决响应大数据表格渲染崩溃问题

如果可以实现记得点赞分享,谢谢老铁~ 1.场景描述 发起请求获取上万条数据,进行表格渲染,使浏览器卡顿,导致网页崩溃。 2.分析原因 1.大量数据加载,过多操作Dom,消耗性能。 2.表格中包含其他…

Linux 基础认识

文章目录 前言Linux历史window历史Linux地位发行版本 前言 建议只看概述 Linux历史 概述: 由一个研究生受Minix操作系统启发编写的,因为功能实用,代码开源被世界人接收和开发 ,最终正式发布 。 详情: 1991年10月5日…

Azure Machine Learning - 在 Azure AI 搜索中创建全文查询

Azure AI搜索中如果要为全文搜索生成查询,本文提供了设置请求的步骤。 本文还介绍了查询结构,并说明了字段属性和语言分析器如何影响查询结果。 关注TechLead,分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&a…

【开源威胁情报挖掘1】引言 + 开源威胁情报挖掘框架 + 开源威胁情报采集与识别提取

基于开源信息平台的威胁情报挖掘综述 写在最前面摘要1 引言近年来的一些新型网络安全威胁类型挖掘网络威胁的情报信息威胁情报分类:内、外部威胁情报国内外开源威胁情报挖掘分析工作主要贡献研究范围和方法 2 开源威胁情报挖掘框架1. 开源威胁情报采集与识别2. 开源…

详解SpringAop开发过程中的坑

😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783…

【Cisco Packet Tracer】DHCP/FTP/WEB/DNS实验

本文使用CiscoPacketTracer仿真软件实现了DHCP/FTP/WEB/DNS实验,拓扑中包含2个客户机和3个服务器(DHCP服务器、DNS服务器、FTP/WEB公用一个服务器),客户机的IP地址由DHCP服务器动态分配。 DHCP服务器IP地址:192.168.0…

renpy-renpy对话内容汉化

文章目录 前言思路实现1,提取对话内容2,汉化对话内容文件3,修改gui文件,使得renpy游戏支持中文显示 前言 最近下载了一些renpy视觉小说内容,发现对话都为英文,因此我在想能否提取出这些对话然后汉化后再封装回原文件,将其汉化 当然汉化过程是机器翻译,汉化其他语言同理,大概5分…

Wireshark使用详解

wireshark简介 wireshark是捕获机器上的某一块网卡的网络包,当你的机器上有多块网卡的时候,你需要选择一个网卡。   wireshark能获取HTTP,也能获取HTTPS,但是不能解密HTTPS,所以wireshark看不懂HTTPS中的内容&#…