1 简介
职责链模式(Chain of Responsibility Pattern)定义:避免请求发送者与接受者耦合在一起,让多个对象都有可能接受请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
2 代码
(1)抽象处理者(Handler)
public abstract class Handler {
protected Handler successor; //后继者
public void setSuccessor(Handler successor) {
this.successor=successor;
}
public abstract void handleRequest(String request);
}
(2)具体处理者(ConcreteHandler)
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(String request) {
if( request满足条件 ) {
... //处理请求
}else {
successor.handleRequest(request); //将职责抛给下家
}
}
}
3 应用案例
假条审批系统:如果学生请假天数小于或等于3天,辅导员可以审批该假条;如果大于3天,小于或等于7天,系主任可以审批;如果大于7天,小于或等于30天,院长可以审批;超过30天,提示相应拒绝信息。
(1)请求类(LeaveRequest)
public class LeaveRequest {
public String leaveName;
public int leaveDays;
public LeaveRequest(String leaveName,int leaveDays) {
this.leaveName=leaveName;
this.leaveDays=leaveDays;
}
}
(2)抽象处理者(Leader)
public abstract class Leader {
String name;
protected Leader successor; //后继者
public Leader(String name) {
this.name=name;
}
public void setSuccessor(Leader successor) {
this.successor=successor;
}
public abstract void handleRequest(LeaveRequest request);
}
(3)具体处理者(Counselor、Director、Dean)
public class Counselor extends Leader {
public Counselor(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.leaveDays<=3) {
System.out.println("辅导员"+name+"审批学生"+request.leaveName+"的请假条,请假天数为"+request.leaveDays+"天");
}else {
successor.handleRequest(request); //将职责抛给下家
}
}
}
public class Director extends Leader {
public Director(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.leaveDays<=7) {
System.out.println("系主任"+name+"审批学生"+request.leaveName+"的请假条,请假天数为"+request.leaveDays+"天");
}else {
successor.handleRequest(request); //将职责抛给下家
}
}
}
public class Dean extends Leader {
public Dean(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.leaveDays<=30) {
System.out.println("院长"+name+"审批学生"+request.leaveName+"的请假条,请假天数为"+request.leaveDays+"天");
}else {
System.out.println("莫非你想休学,居然请假"+request.leaveDays+"天");
}
}
}
(4)客户端(Client)
public class Client {
public static void main(String[] args) {
Leader counselor=new Counselor("张三");
Leader director=new Director("李四");
Leader dean=new Dean("王五");
counselor.setSuccessor(director);
director.setSuccessor(dean);
counselor.handleRequest(new LeaveRequest("stuA",2));
counselor.handleRequest(new LeaveRequest("stuB",6));
counselor.handleRequest(new LeaveRequest("stuC",15));
counselor.handleRequest(new LeaveRequest("stuD",40));
}
}
辅导员张三审批学生stuA的请假条,请假天数为2天
系主任李四审批学生stuB的请假条,请假天数为6天
院长王五审批学生stuC的请假条,请假天数为15天
莫非你想休学,居然请假40天
4 JDK中应用
在早期的 Java AWT 事件模型(JDK 1.0及更早),广泛使用了职责链模式,这种事件处理机制又叫事件浮升(Event Bubbling)机制。
由于窗口组件(如按钮、文本框等)一般都位于容器组件中,因此当事件发生在某一个组件上时,通过组件对象的 handleEvent() 方法将事件传递给相应的事件处理方法,该事件处理方法将处理此事件,然后决定是否将该事件向上一级容器组件传播,如果没有相应的事件处理方法,则会将事件传递给包含组件的上一级容器,以此类推;上一级容器组件在接到事件之后可以继续处理此事件,并决定是否继续向上级容器组件传播,如此反复,直到事件到达顶层容器组件为止;如果一直传到最顶层容器仍没有处理方法,则该事件不予处理。
由于这种基于职责链模式的事件处理方式存在代码维护困难、重用性差、存在大量条件语句、处理速度慢等缺点,从JDK 1.1 以后,使用观察者模式代替职责链模式来处理事件。目前,在 JavaScript 中仍然可以使用这种事件浮升机制来进行事件处理。