目录
1、概述
(1)应用场景与实际问题
a.报销单审批
很多人工作需要出差,出差后需要填写报销单,填写后还要层层领导审批,比如直属领导-部门经理-财务主管。。。
小金额(3000以下)可能是三级审批,大金额(3000以上)可能要四级审批。而审批过程中,每一级领导都可能做出通过或驳回的操作。
与之类似的,还有各类审批单,比如采购需求单、资源申请单,等等的审批流场景。
b.注册信息校验
我们注册一个网站会员,需要校验身份证号码是否合法正确,需要校验手机号码是否有效,需要校验地址是否真实有效、需要校验头像是否与身份证上一致,等等。
c.购物场景
一个购物下单请求来了,我们需要校验库存是否够、购买权限是否正常、支付情况、物流配送单位等等。
以上场景,我们常常将校验逻辑写到一起,通过一堆if...else拼接。但是校验逻辑逐渐复杂,再来个新需求改动,那倒不如全部推倒重写。。。
所以,就到了责任链模式大显身手的时候了。
(2)责任链模式定义
责任链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。
a.优点
请求的发送者和接收者(请求的处理)解耦。
责任链可以动态组合。可以消除大部分if...else的判断。
b.缺点
链太长的话,影响性能。如果链上的多个节点中,只有一个有资格处理某个对象的请求,但是需要沿着链一个一个往后流转,直至流转到可以处理当前对象请求的的节点那里。 这就像数组和链表的取值区别一样,取数组下标为4的数可以直接取,但取链表的第几个节点的值时,xu
2、代码
(1)场景
假如一个课程由视频和文章笔记组成,每次发布提交,都需要专门有人进行审核把关,只有在层层把关通过后,才可以顺利上线。
这里我们构建一个(抽象类)审批者Approver,不同方面不同层次的审核都通过继承该抽象类进行具体定义。
同时,关键要指定下一层审批类。即每个审批类不仅要实现具体某个方面的审批校验,同时还要指定下一个审批者是谁,下一棒交到谁手里。就像链表,每个节点不仅要保存数据,还必须要指定下一个节点是哪个,最终才能形成完整的链条。
(2)类图
(3)关键的类
全部代码可以在这里:
package behavioral.chainofresponsibility;
//批准者
public abstract class Approver {
protected Approver approver;
public void setNextApprover(Approver approver) {
this.approver=approver;
}
//发布课程
public abstract void deploy(Course course);
}
package behavioral.chainofresponsibility;
public class AticleApprover extends Approver{
@Override
public void deploy(Course course) {
if (course.getArticle()!=null&&!course.getArticle().equals("")) {
System.out.println(course.getName()+"含有文章手记,内容正常,批准");
if (approver!=null) {
approver.deploy(course);
}
}else {
System.out.println(course.getName()+"不含有文章手记或内容不正常,不批准,流程结束");
return;
}
}
}
package behavioral.chainofresponsibility;
public class VideoApprover extends Approver{
@Override
public void deploy(Course course) {
if (course.getVideo()!=null&&!course.getVideo().equals("")) {
System.out.println(course.getName()+"含有视频,内容正常,批准");
if (approver!=null) {
approver.deploy(course);
}
}else {
System.out.println(course.getName()+"不含有视频或内容不正常,不批准,流程结束");
return;
}
}
}
最后是在Test类中,指定了审批类之间的关联关系,即先通过谁审批,再通过谁审批。
package behavioral.chainofresponsibility;
public class Test {
public static void main(String[] args) {
Approver articleApprover=new AticleApprover();
Approver videoApprover=new VideoApprover();
Course course=new Course();
course.setName("XX课程");
course.setArticle("详细手记文章");
course.setVideo("详细视频讲解");
articleApprover.setNextApprover(videoApprover);
articleApprover.deploy(course);
}
}
3、项目源码
一般我们在项目源码中看到诸如XXXChain,XXXHandler的时候,一般我们就可以往责任链模式上靠了。是不是有一个统一的抽象类或接口,是不是每个子类分别实现了不同的校验,并且还定义了下一个要流向的子类。
比如,在sevlet包中,有一个叫FilterChain的接口,它定义了对于请求的过滤方法。而其实现类比如MockFilterChain类,则集合了众多的Filter过滤器,同时定义了过滤器使用的流向。Filter本身是个接口,有众多实现类。
坦克大战代码中对于责任链模式的应用介绍在这里:
https://blog.csdn.net/phs999/article/details/107453246