职责链模式

职责链模式是一种设计模式,用于创建一个处理请求的对象链。模式中,每个处理者都可以处理请求,若无法处理则将请求传递给下个处理者。在学校的采购审批案例中,通过职责链模式,避免了传统方案中的分支判断,降低了审批系统中各部分的耦合,提高了代码的可维护性。然而,过长的职责链可能影响性能,需要注意控制链的长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、职责链模式介绍

      职责链模式,又叫责任链模式,为请求创建了一个接受者对象的链。这种模式对请求的发送者和接受者进行解耦。职责链模式中,每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依次类推。

       职责链模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

二、职责链模式原理

说明:

1)Handler:抽象的处理者。定义了一个处理请求的接口,同时含有另外Handler

2)ConcreteHandlerA/ConcreteHandlerB:具体的处理者。处理它自己负责的请求,可以访问它的后继者(即下一个处理者)。如果可以处理当前请求,则处理,否则就将该请求交个后继者去处理,从而形成一个职责链

3)request:含有多个属性,表示一个请求

三、职责类模式例子

       学校有OA系统的采购审批项目,需求是:1)采购员采购教学器材;2)如果金额小于等于5000,由教学主任审批;3)如果金额小于等于10000;由院长审批;4)如果金额小于等于30000,由副院长审批;5)如果金额超过30000以上,由校长审批。请设计程序完成采购审批项目。

第一种解决方案:传统方案

       传统方式是接收到一个采购请求后,根据采购金额来调用对应的Approver完成审批。但在传统方式中,客户端会使用到分支判断来对不同的采购请求处理,这样存在如下问题:①如果各个级别的人员审批金额发生变化,在客户端也需要变化;②客户端必须明确地知道有多少个审批级别和访问。这样对一个采购请求进行处理和Approver就存在强耦合关系,不利于代码的维护。我们可以使用职责链模式来解决上述问题。

第二种解决方案:职责链模式

类图如下所示:

代码如下所示:

创建PurchaseRequest类:

//请求类
public class PurchaseRequest{

    //请求类型
    private int type = 0;

    private float price = 0.0f;

    private int id = 0;

    public PurchaseRequest(int type, float price, int id){
        this.type = type;
        this.price = price;
        this.id = id;
    }

    public int getType(){
        return type;
    }

    public float getPrice(){
        return price;
    }

    public int getId(){
        return id;
    }
}

创建Approver抽象类及其子类:

public abstract class Approver{

    private String name;

    //下一个处理者
    Approver approver;

    public Approver(String name){
        this.name = name;
    }

    //下一个处理者
    public void setApprover(Approver approver){
        this.approver = approver;
    }

    //处理审批请求的方法,得到一个请求,处理是子类完成,因此该方法做成抽象
    public abstract void processRequest(PruchaseRequest request);    
}
public class DepartmentApprover extends Approver{

    public DepartmentApprover(){
        super(name);
    }

    public void processRequest(PurchaseRequest request){
        if(request.getPrice() <= 5000){
            System.out.println("请求编号id =>" + request.getId() + "被" + this.name + "审批");
        } else {
            approver.processRequest(request);
        }
    }
}
public class CollegeApprover extends Approver{

    public CollegeApprover(){
        super(name);
    }

    public void processRequest(PurchaseRequest request){
        if(request.getPrice() > 5000 && request.getPrice() <= 10000){
            System.out.println("请求编号id =>" + request.getId() + "被" + this.name + "审批");
        } else {
            approver.processRequest(request);
        }
    }
}
public class ViceSchoolMasterApprover extends Approver{

    public ViceSchoolMasterApprover(){
        super(name);
    }

    public void processRequest(PurchaseRequest request){
        if(request.getPrice() > 10000 && request.getPrice() <= 30000){
            System.out.println("请求编号id =>" + request.getId() + "被" + this.name + "审批");
        } else {
            approver.processRequest(request);
        }
    }
}
public class SchoolMasterApprover extends Approver{

    public SchoolMasterApprover(){
        super(name);
    }

    public void processRequest(PurchaseRequest request){
        if(request.getPrice() > 30000){
            System.out.println("请求编号id =>" + request.getId() + "被" + this.name + "审批");
        } else {
            approver.processRequest(request);
        }
    }
}

创建Client类:

public class Client{

    public static void main(String[] args){
        PurchaseRequest request = new PurchaseRequest(1, 31000F, 1);

        DepartmentApprover deptApprover = new DepartmentApprover("张主任");
        CollegeApprover collegeApprover = new CollegeApprover("李院长");
        ViceSchoolMasterApprover vsmApprover = new ViceSchoolMasterApprover("王副校长");
        SchoolMasterApprover smApprover = new SchoolMasterApprover("陈校长");

        deptApprover.setApprover(collegeApprover);
        collegeApprover.setApprover(vsmApprover);
        vsmApprover.setApprover(smApprover);
        smApprover.setApprover(deptApprover);

        deptApprover.processRequest(request);
    }
}

四、职责链模式注意事项和细节

1)将请求和处理分开,实现解耦,提高系统的灵活性

2)简化了对象,使对象不需要知道链结构

3)性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在Handler中设置一个最大节点数量,在setNext()方法中判断是否已经超过阈值,超过则不允许该链建立,避免出现超长链而破坏系统性能

4)调试不方便,采用了类似递归的方法,调试时逻辑可能比较复杂

5)最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求、请假/加薪等审批流程、Java web中Tomcat对Encoding的处理、拦截器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值