设计模式之责任链模式
Posted ProChick
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之责任链模式相关的知识,希望对你有一定的参考价值。
1.简要概述
- 责任链模式也叫作职责链模式,属于行为型设计模式。
- 责任链模式将能够处理同一类请求的对象连成一条链,所提交的请求会沿着这条链进行依次处理。
- 责任链模式中,通常会在每一个请求处理者中都包含下一个请求处理者的引用,如果一个请求不能够被当前处理者处理,则传递到这条链的下一个请求处理者对象,以此类推。
- 责任链模式中,一个处理者对象通常只有两个行为,一是处理请求,二是将请求传递给下一个处理者,不允许某个处理者对象在处理了请求后又将请求传递给上一个处理者的情况。
2.模式结构
👉通常由一个处理者抽象类(
负责定义处理请求的接口,同时维护下一个具体处理者的对象引用
),多个具体的处理者类(负责实现自己对该请求处理的逻辑方法,然后将请求传递到下一个请求处理者
),一个请求者类(负责创建一个请求对象
),一个客户类(负责对请求者类和处理者类进行调用,通过处理链条完成对请求的依次处理
)共同组成。
3.实现代码
举例 💡 :假设在学校中,学生提出请假请求会根据请假的天数,需要去找不同层次的领导进行依次审批,如果全部审批通过则该请假才能够生效。那么对请假请求进行审批的流程,我们就可以使用责任链模式进行处理。
请假请求(请求者类)
public class LeaveRequest {
// 请假天数
private int day;
public LeaveRequest(int day) {
this.day = day;
}
public int getDay(){
return this.day;
}
}
领导(处理者抽象类)
public abstract class Leader {
protected String leaderName;
protected Leader nextLeader;
public RequestLeader(String leaderName) {
this.leaderName = leaderName;
}
// 设置下一个处理者
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
// 处理的抽象方法
public abstract void handle(LeaveRequest request);
}
班级领导(具体处理者类)
public class ClassesLeader extends Leader{
public ClassesLeader(String leaderName) {
super(leaderName);
}
@Override
public void handle(LeaveRequest request) {
if(request.getDay() > 0 && request.getDay() <= 3){
System.out.println(this.leaderName + "同意审批!");
}
else{
System.out.println("请求交由院级领导审批!");
this.nextLeader.handle(request);
}
}
}
院级领导(具体处理者类)
public class AcademyLeader extends Leader{
public AcademyLeader(String leaderName) {
super(leaderName);
}
@Override
public void handle(LeaveRequest request) {
if(request.getDay() > 3 && request.getDay() <= 7){
System.out.println(this.leaderName + "同意审批!");
}
else{
System.out.println("请求交由校级领导审批!");
this.nextLeader.handle(request);
}
}
}
校级领导(具体处理者类)
public class SchoolLeader extends Leader{
public SchoolLeader(String leaderName) {
super(leaderName);
}
@Override
public void handle(LeaveRequest request) {
if(request.getDay() > 7){
System.out.println(this.leaderName + "同意审批!");
}
else{
System.out.println("该请求不能审批!");
}
}
}
客户类
// 测试客户端
public class LeaveClient{
public static void main(String[] args) {
// 创建请求
LeaveRequest request = new LeaveRequest(5);
// 创建领导建立责任链
ClassesLeader leader1 = new ClassesLeader("李班长");
AcademyLeader leader2 = new AcademyLeader("张院长");
SchoolLeader leader3 = new SchoolLeader("王校长");
leader1.setNextLeader(leader2);
leader2.setNextLeader(leader3);
// 处理请求
leader1.handle(request);
}
}
4.优点好处
- 在责任链模式中,简化了对象之间的连接关系,每个对象只需保持一个指向其后继者的引用,不需保持所有处理者的引用,这就避免了使用众多的条件判断语句。
- 在责任链模式中,我们可以很容易的根据需要增加或者移除责任链上的某个对象,并且不会对原有的其它对象进行修改,所以符合开闭原则。
- 在责任链模式中,每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
- 在责任链模式中,增强了给对象指派职责的灵活性,当工作流程发生变化,可以动态地改变链内成员的执行次序。
- 在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递。
- 在责任链模式中,降低了对象之间的耦合度,一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
5.缺点弊端
- 当处理一个请求所需要用到的处理类较多时,会导致处理的链条比较长,那么就很有可能导致程序的逻辑相对复杂,并且有可能会对系统的性能产生影响。
- 不能保证每个请求一定被处理,由于请求没有明确的接收者,所以不能保证它一定会被处理。
- 职责链设计的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
6.应用场景
- 当系统中的多个对象可以处理同一个请求,但具体由哪个对象进行处理又不确定,只能在运行时动态决定的时候,就可以使用责任链模式。
- 当系统中需要为一个请求动态的添加处理方法的时候,就可以使用责任链模式。
- 在Java中,一个try语句可以对应多个catch语句,如果异常不能被当前catch语句进行捕获,则会跳到下一个catch语句进行捕获,所以异常的捕获机制就采用了责任链模式。
- 在Java的Web开发中,过滤器的过滤机制也是采用的责任链模式。
7.应用示例
在Java Servlet源码中,Filter过滤器类的设计就采用了责任链模式
-
这里的Filter接口就可以看作是责任链模式中的处理者抽象类,里面定义了一个叫做doFilter的处理接口方法。在Filter的各种实现类中,完成了对doFilter的实现。
-
下面以XssFilter类为例,在内部完成了对doFilter方法的实现,并且可以看到在完成处理后,又通过FilterChain这个类的对象继续传递给下一个Filter进行请求的处理。
-
虽然在Filter类中没有聚合下一个Filter的引用,但是在Filter的实现类中我们可以发现,都是通过ChainFilter这个类完成的链式调用。其实在ChainFilter接口的实现类中定义了一个filters集合,专门用于维护处理当前请求所需要用到的所有Filter对象,然后通过nextFilter进行依次调用。
-
通过上述的描述过程可以看出,这里的Filter过滤器处理请求的过程采用了责任链模式进行设计。
以上是关于设计模式之责任链模式的主要内容,如果未能解决你的问题,请参考以下文章