郴州网站建设哪家比较好,重庆开网站,网络营销的特点和功能,Checkout v1.4.1 WordPress主题大家好#xff0c;我是晴天。我们又见面了#xff0c;本周我们继续学习设计模式#xff0c;本周将同大家一起学习责任链模式。 场景引入
我们回想一下自己曾经经历过的考学场景#xff0c;我们是如何一步一步考上大学的#xff08;为了简化过程只提取核心环节#xff09… 大家好我是晴天。我们又见面了本周我们继续学习设计模式本周将同大家一起学习责任链模式。 场景引入
我们回想一下自己曾经经历过的考学场景我们是如何一步一步考上大学的为了简化过程只提取核心环节。第一步我们需要报名考试第二步我们需要去参加考试第三步我们才能够通过考试顺利进入大学。这三个步骤必须要串行化执行只有前一步通过了我们才能进行后续的步骤如果前一步没有通过则提前终止整过流程无需进行后续步骤了。
什么是责任链模式 责任链设计模式是一种行为型设计模式它要求完成一件事情必须按照指定顺序进行前一个环节完成了才能进行下一个环节否则就提前终止。每个环节可以理解成一个链表的节点当这个节点接收到上一个节点传送过来的信息时开始进行自身的逻辑处理处理完成后传递给下一个节点调用下一个节点的处理方法直到链表遍历完成为止。
为什么需要责任链模式
责任链设计模式是一种行为型设计模式它主要用于将请求沿着处理链传递直到有一个处理者能够处理该请求为止。责任链模式有助于降低发送者和接收者之间的耦合度使系统更加灵活和可扩展。
代码实战
实现顺序执行逻辑有两种处理方法一种遍历方式是将处理方法放到数组中遍历处理方法即可第二种就是使用责任链模式来处理。我们依次来看一下这两种实现方式。
遍历方式
package mainimport (contexterrorsfmt
)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 不需要调用下一个节点了已经是最后一个节点了。
两种处理方式的对比
遍历方式优点
遍历方式结构简单能够方便地将处理方法按照指定顺序对请求进行处理。
遍历方式缺点
每个处理方法之间没有必然的联系无法通过上一个处理方法找到写一个处理方法关联性不强。
责任链模式优点
节点之间相互串联关联性比较强当前节点可以根据自身节点的处理结果来决定是否将请求继续向下传递。执行一整条责任链的逻辑处理只需要调用头节点处理方法即可就像是只调用了一个节点的处理方法一样。
总结
本文我们介绍了什么是责任链模式为什么需要责任链模式遍历方式和责任链模式的使用方法并且对比了遍历方式和责任链模式的优缺点。希望各位读者小伙伴能有些许收获。
写在最后
感谢大家的阅读晴天将继续努力分享更多有趣且实用的主题如有错误和纰漏欢迎留言给予指正。 更多文章敬请关注作者个人公众号 晴天码字。 我们下期不见不散to be continued…