6.1、介绍
责任链模式(Chain of Responsibility),又叫职责链模式,为请求创建了一个接收者对象的链。这种模式对请求的发送者和接收者进行解耦。
责任链模式通过每个接收者包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同请求传给下一个接收者,以此类推。
这种类型的设计模式属于行为型模式。
6.2、代码支撑
举例:新学期学校需要采购一批新的设备,采购员需要根据不同的金额向不同的级别申请审批。如果金额小于等于5000,由教学主任审批;如果金额小于等于10000,由院长审批;如果金额小于等于30000,由副校长审批;如果金额超过30000,由校长审批。请设计合适的程序处理该请求。
首先创建一个采购请求类 PurchaseRequest.java
,并自定义一些采购信息:
public class PurchaseRequest {
private int id = 0;// 请求编号
private float price = 0.0f;// 请求的金额
public PurchaseRequest(int id, float price) {
this.id = id;
this.price = price;
}
public int getId() {
return id;
}
public float getPrice() {
return price;
}
}
审批请求处理 Approver.java
:
public abstract class Approver {
Approver approver;// 下一个处理者
String name;// 名字
public Approver(String name) {
this.name = name;
}
// 下一个处理者
public void setApprover(Approver approver) {
this.approver = approver;
}
// 处理审批请求的方法,得到一个请求,处理是由子类完成的,故该方法是抽象方法
public abstract void processRequest(PurchaseRequest purchaseRequest);
}
下面是各级审批人,都继承类 Approver.java
,处理审批金额小于等于5000的教学主任 DepartmentApprover.java
:
public class DepartmentApprover extends Approver {
public DepartmentApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice() <= 5000){
System.out.println("请求编号" + purchaseRequest.getId() + "需要金额¥" + purchaseRequest.getPrice() + ",被" + this.name + "处理");
} else {
approver.processRequest(purchaseRequest);
}
}
}
处理审批金额小于等于10000的院长 CollegeApprover.java
:
public class CollegeApprover extends Approver {
public CollegeApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000){
System.out.println("请求编号" + purchaseRequest.getId() + "需要金额¥" + purchaseRequest.getPrice() + ",被" + this.name + "处理");
} else {
approver.processRequest(purchaseRequest);
}
}
}
处理审批金额小于等于30000的副校长 VicePrincipalApprover.java
:
public class VicePrincipalApprover extends Approver {
public VicePrincipalApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000){
System.out.println("请求编号" + purchaseRequest.getId() + "需要金额¥" + purchaseRequest.getPrice() + ",被" + this.name + "处理");
} else {
approver.processRequest(purchaseRequest);
}
}
}
处理审批金额超过30000的校长 PrincipalApprover.java
:
public class PrincipalApprover extends Approver {
public PrincipalApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice() > 30000){
System.out.println("请求编号" + purchaseRequest.getId() + "需要金额¥" + purchaseRequest.getPrice() + ",被" + this.name + "处理");
} else {
approver.processRequest(purchaseRequest);
}
}
}
创建一个客户端类 Client.java
进行测试:
public class Client {
public static void main(String[] args) {
// 创建一个请求
PurchaseRequest purchaseRequest1 = new PurchaseRequest(1, 3000);
PurchaseRequest purchaseRequest2 = new PurchaseRequest(2, 8000);
PurchaseRequest purchaseRequest3 = new PurchaseRequest(3, 30001);
// 创建相关的级别审批人
DepartmentApprover departmentApprover = new DepartmentApprover("张主任");
CollegeApprover collegeApprover = new CollegeApprover("李院长");
VicePrincipalApprover vicePrincipalApprover = new VicePrincipalApprover("王副校");
PrincipalApprover principalApprover = new PrincipalApprover("刘校长");
// 将各个级别的下一个审批人设置好,审批人之间要构成一个环形
departmentApprover.setApprover(collegeApprover);
collegeApprover.setApprover(vicePrincipalApprover);
vicePrincipalApprover.setApprover(principalApprover);
principalApprover.setApprover(departmentApprover);
// 测试
collegeApprover.processRequest(purchaseRequest1);
collegeApprover.processRequest(purchaseRequest2);
collegeApprover.processRequest(purchaseRequest3);
}
}
控制台运行结果如下:
6.3、总结
责任链模式优点:
- 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
- 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
- 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
- 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
责任链模式缺点:
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 对比较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于责任链的错误设置而导致系统出错,比如可能会造成循环调用。