1.责任链模式简介(Chain of Responsibility)
定义:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
注意:责任链模式也叫职责链模式。
在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,所以责任链将请求的发送者和请求的处理者解耦了。
2.责任链模式的角色
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
3.责任链模式简单案例
案例:一般公司请假都会按照请假天数经手不同职级的人来审批,我们就以此来使用责任链模式简单说明一下;
被责任链处理的消息 承载对象
/**
* 被责任链处理的消息 承载对象
*/
public class A1_Request {
/**
* 请求者名称
*/
private String personName;
/**
* 休息天数
*/
private int restDay;
public A1_Request(){}
public A1_Request(String personName, int restDay) {
this.personName = personName;
this.restDay = restDay;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public int getRestDay() {
return restDay;
}
public void setRestDay(int restDay) {
this.restDay = restDay;
}
}
抽象处理者(Handler)
/**
* 抽象处理者(Handler)
*/
public abstract class B1_Manager {
public static int DayUnit1 = 3;
public static int DayUnit2 = 12;
public static int DayUnit3 = 30;
//管理者的职务
protected String managerJob;
//上级管理者
protected B1_Manager superior;
public B1_Manager(String managerJob) {
this.managerJob = managerJob;
}
//审批操作
public abstract boolean examineApprove(A1_Request request);
public B1_Manager getSuperior() {
return superior;
}
public void setSuperior(B1_Manager superior) {
this.superior = superior;
}
}
具体处理者:经理审批
/**
* 具体处理者:经理审批
*/
public class C1_M1 extends B1_Manager {
public C1_M1(String managerJob){
super(managerJob);
}
@Override
public boolean examineApprove(A1_Request request) {
if(request.getRestDay()<=B1_Manager.DayUnit1){
System.out.println(String.format("%s-请假[%s]天 ~ %s:审批通过",request.getPersonName(),request.getRestDay(),this.managerJob));
return true;
}else if(null!=this.superior){
return this.superior.examineApprove(request);
}
System.out.println(String.format("%s-请假[%s]天 ~ 无人审批",request.getPersonName(),request.getRestDay()));
return false;
}
}
具体处理者:总监审批
/**
* 具体处理者:总监审批
*/
public class C1_M2 extends B1_Manager {
public C1_M2(String managerJob){
super(managerJob);
}
@Override
public boolean examineApprove(A1_Request request) {
if(request.getRestDay()<=B1_Manager.DayUnit2){
System.out.println(String.format("%s-请假[%s]天 ~ %s:审批通过",request.getPersonName(),request.getRestDay(),this.managerJob));
return true;
}else if(null!=this.superior){
return this.superior.examineApprove(request);
}
System.out.println(String.format("%s-请假[%s]天 ~ 无人审批",request.getPersonName(),request.getRestDay()));
return false;
}
}
具体处理者:CEO审批
/**
* 具体处理者:CEO审批
*/
public class C1_M3 extends B1_Manager {
public C1_M3(String managerJob){
super(managerJob);
}
@Override
public boolean examineApprove(A1_Request request) {
if(request.getRestDay()<=B1_Manager.DayUnit3){
System.out.println(String.format("%s-请假[%s]天 ~ %s:审批通过",request.getPersonName(),request.getRestDay(),this.managerJob));
return true;
}else if(null!=this.superior){
return this.superior.examineApprove(request);
}
System.out.println(String.format("%s-请假[%s]天 ~ 无人审批",request.getPersonName(),request.getRestDay()));
return false;
}
}
客户类(Client)角色
/**
* 客户类(Client)角色
*/
public class D1_Client {
public static void main(String[] args) {
B1_Manager m1 = new C1_M1("经理");
B1_Manager m2 = new C1_M2("总监");
B1_Manager m3 = new C1_M3("CEO");
m1.setSuperior(m2);
m2.setSuperior(m3);
A1_Request request1 = new A1_Request("张三",1);
A1_Request request2 = new A1_Request("李四",9);
A1_Request request3 = new A1_Request("王五",30);
A1_Request request4 = new A1_Request("赵六",35);
m1.examineApprove(request1);
m1.examineApprove(request2);
m1.examineApprove(request3);
m1.examineApprove(request4);
}
}
客户端调用结果
张三-请假[1]天 ~ 经理:审批通过
李四-请假[9]天 ~ 总监:审批通过
王五-请假[30]天 ~ CEO:审批通过
赵六-请假[35]天 ~ 无人审批
4.责任链模式的优点
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
5.责任链模式的缺点
- 不能保证请求一定被接收。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
- 可能不容易观察运行时的特征,有碍于除错。
6.责任链模式的应用场景
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求。