您现在的位置是:首页 >学无止境 >设计模式-责任链模式网站首页学无止境
设计模式-责任链模式
问题背景
学校OA系统采购审批项目:需求时
1)采购员采购教学器材
2)如果金额小于等于5000,由教学主任审批
3)如果金额小于等于10000,由院长审批
4)如果金额小于等于30000,由副校长审批
5)如果金额小于等于40000,由校长审批
请设计完成采购审批项目
解决方案:传统方法
我们在程序里直接使用 if else 语句来判断这个审批交给谁来审批。
这样是最简单的,大家都知道该如何去写这样的代码。但是这样的代码和审批人是强耦合关系,非常不利于代码的扩展和维护。
责任链模式
基本介绍
1)职责链模式(Chain of Responsibility Pattern)又叫责任链模式,为请求创建一个接收者对象的链。这种模式对请求的发送者和接收者进行耦合。
2)职责链模式通常每个接受者都包含另一个对象接收者的引用。如果一个对象不能处理该请求,那么他会把相同的请求传给下一个接收者,依次类推。
3)这种类型的设计模式属于行为模式
UML类图
1)Handler抽象类定义了一个处理请求的接口,同时包含下一个Handler
2)ConcreteHandlerA、B是具体的处理者,处理它自己负责的请求,可以访问它的后继者(即处理下一个处理者),如果可以处理当前请求,则处理,否则就将该请求交给后续者去处理,从而形成一个职责链
3)Request类是全局的上下文,包含了很多属性,表示一个请求
职责链模式使多个对象都有机会处理请求,从而避免请求发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这个链条传递该请求,直到有一个对象处理它为止。
解决方案:责任链模式
UML类图
代码示例
public abstract class Approver {
/**
* 下一个节点
*/
private Approver approver;
public Approver getApprover() {
return approver;
}
public void setApprover(Approver approver) {
this.approver = approver;
}
/**
* 处理请求
*
* @param purchaseRequest
*/
public abstract void processRequest(PurchaseRequest purchaseRequest);
}
public class PurchaseRequest {
/**
* 金额
*/
private Integer money;
/**
* 是否通过
*/
private Boolean flag = Boolean.FALSE;
/**
* 审批通过人
*/
private String name;
public PurchaseRequest(Integer money) {
this.money = money;
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
public Integer getMoney() {
return money;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class DepartmentApprover extends Approver{
/**
* 节点名称
*/
private String name = "教学主任";
/**
* 支持审批的金额
*/
private Integer money;
/**
* 构造器要传入下一个处理节点
*
*/
public DepartmentApprover(Integer money) {
this.money = money;
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
// 代表审批通过了
if (purchaseRequest.getFlag()) {
return;
}
if (purchaseRequest.getMoney() <= money) {
purchaseRequest.setFlag(Boolean.TRUE);
purchaseRequest.setName(this.name);
} else {
if (super.getApprover() != null) {
super.getApprover().processRequest(purchaseRequest);
}
}
}
}
public class CollegeApprover extends Approver{
/**
* 节点名称
*/
private String name = "院长";
/**
* 支持审批的金额
*/
private Integer money;
/**
* 构造器要传入下一个处理节点
*
*/
public CollegeApprover(Integer money) {
this.money = money;
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
// 代表审批通过了
if (purchaseRequest.getFlag()) {
return;
}
if (purchaseRequest.getMoney() <= money) {
purchaseRequest.setFlag(Boolean.TRUE);
purchaseRequest.setName(this.name);
} else {
if (super.getApprover() != null) {
super.getApprover().processRequest(purchaseRequest);
}
}
}
}
public class ViceSchoolMasterApprover extends Approver{
/**
* 节点名称
*/
private String name = "副校长";
/**
* 支持审批的金额
*/
private Integer money;
/**
* 构造器要传入下一个处理节点
*
*/
public ViceSchoolMasterApprover(Integer money) {
this.money = money;
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
// 代表审批通过了
if (purchaseRequest.getFlag()) {
return;
}
if (purchaseRequest.getMoney() <= money) {
purchaseRequest.setFlag(Boolean.TRUE);
purchaseRequest.setName(this.name);
} else {
if (super.getApprover() != null) {
super.getApprover().processRequest(purchaseRequest);
}
}
}
}
public class SchoolMasterApprover extends Approver{
/**
* 节点名称
*/
private String name = "校长";
/**
* 支持审批的金额
*/
private Integer money;
/**
* 构造器要传入下一个处理节点
*
*/
public SchoolMasterApprover(Integer money) {
this.money = money;
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
// 代表审批通过了
if (purchaseRequest.getFlag()) {
return;
}
if (purchaseRequest.getMoney() <= money) {
purchaseRequest.setFlag(Boolean.TRUE);
purchaseRequest.setName(this.name);
} else {
if (super.getApprover() != null) {
super.getApprover().processRequest(purchaseRequest);
}
}
}
}
测试用例
public class Client {
public static void main(String[] args) {
// 构建职责链节点
DepartmentApprover departmentApprover = new DepartmentApprover(5000);
CollegeApprover collegeApprover = new CollegeApprover(10000);
ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover(30000);
SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover(40000);
// 构建职责链
departmentApprover.setApprover(collegeApprover);
collegeApprover.setApprover(viceSchoolMasterApprover);
viceSchoolMasterApprover.setApprover(schoolMasterApprover);
// 创建请求
PurchaseRequest purchaseRequest = new PurchaseRequest(8000);
// 传入职责链进行审批
departmentApprover.processRequest(purchaseRequest);
// 查看结果
System.out.println("是否审批通过:" + purchaseRequest.getFlag() + "审批人:" + purchaseRequest.getName());
}
}
运行结果
注意事项和细节
1)将请求和处理分开,实现解耦,提高系统的灵活性
2)简化了对象,使对象不需要知道链的结构
3)性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在Handler中设置一个最大节点数量,在setNext()方法中判断是否已经超过阀值超过则不允许该链建立,避免出现超长链无意识地破坏系统性能
4)调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂
5)最佳应用场景:有多个对象可以处理同一个请求时,比如: 多级请求、请假/加薪等审批流程、Java Web中Tomcat对Encoding的处理、拦截器