设计模式行为型——责任链模式

目录

什么是责任链模式

责任链模式的实现

责任链模式角色

责任链模式类图

责任链模式举例

责任链模式代码实现

责任链模式的特点

优点

缺点

使用场景

注意事项

实际应用


什么是责任链模式

        责任链模式(Chain of Responsibility Pattern)又叫职责链模式是一种行为型设计模式,它通过建立一个对象链来依次处理请求,将请求的发送者和接收者解耦,并允许多个对象都有机会处理请求。其目的是为了解决请求端与实现端的解耦。其实现过程类似递归调用。责任链模式的核心是定义责任链节点的接口以及节点之间的关系,它允许动态的增加和修改责任链中的节点。

责任链模式的实现

责任链模式角色

  1. 抽象处理者(Handler):定义了处理请求的接口,并维护一个指向下一处理者的引用。通常包含一个处理方法 handleRequest()。
  2. 具体处理者(ConcreteHandler):实现了抽象处理者接口,对请求进行具体处理,如果自身无法处理,则将请求转发给下一处理者。

责任链模式类图

责任链模式举例

        以公司采购审批为例,不同金额的采购需要不同人员的审批,比如20000以下需要项目经理审批,20000-50000需要部门经理审批,50000以上需要总经理审批。此时我们把审批流程可以看作一个审批责任链条,进而可以使用责任链模式。

责任链模式代码实现

实体请求类

package com.common.demo.pattern.chain;

import java.math.BigDecimal;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 实体请求类
 * @date 2023/07/27 13:35:41
 */
public class PurchaseReq {

    /**
     * 请求类型
     */
    private int type;

    /**
     * 金额
     */
    private BigDecimal price;

    /**
     * 用途
     */
    private String purpose;

    public PurchaseReq(int type, BigDecimal price, String purpose) {
        this.type = type;
        this.price = price;
        this.purpose = purpose;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public String getPurpose() {
        return purpose;
    }

    public void setPurpose(String purpose) {
        this.purpose = purpose;
    }

    @Override
    public String toString() {
        return "PurchaseReq{" +
                "type=" + type +
                ", price=" + price +
                ", purpose=" + purpose +
                '}';
    }
}

抽象处理者角色

package com.common.demo.pattern.chain;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 抽象审批者处理类, 抽象处理者角色
 * @date 2023/07/27 13:44:42
 */
public abstract class Approver {

    Approver approver;
    String name;

    public Approver() {
    }

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

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



    /**
     * 处理审批请求的方法,得到一个请求,处理是子类实现
     */
    public abstract void process(PurchaseReq purchaseReq);

}

具体处理者角色

package com.common.demo.pattern.chain;

import java.math.BigDecimal;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 项目经理 具体审批者
 * @date 2023/07/27 13:49:16
 */
public class ProjectManager extends Approver {

    public ProjectManager(String name) {
        super(name);
    }

    @Override
    public void process(PurchaseReq purchaseReq) {
        // 小于 5000 项目经理审批即可
        if (purchaseReq.getPrice().compareTo(new BigDecimal(5000)) == -1) {
            System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");
        } else {
            System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");
            approver.process(purchaseReq);
        }
    }
}
package com.common.demo.pattern.chain;

import java.math.BigDecimal;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 部门经理 具体审批者
 * @date 2023/07/27 13:49:48
 */
public class DepartmentManager extends Approver{

    public DepartmentManager(String name) {
        super(name);
    }

    @Override
    public void process(PurchaseReq purchaseReq) {
        // 小于 20000 大于 5000, 部门经理审批即可
        if(purchaseReq.getPrice().compareTo(new BigDecimal(20000))==-1){
            System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");
        } else {
            System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");
            approver.process(purchaseReq);
        }
    }
}
package com.common.demo.pattern.chain;

import java.math.BigDecimal;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 总经理 具体审批者
 * @date 2023/07/27 13:50:45
 */
public class GeneralManager extends Approver {

    public GeneralManager(String name) {
        super(name);
    }

    @Override
    public void process(PurchaseReq purchaseReq) {
        // 大于 20000 ,总经理审批
        if (new BigDecimal(20000).compareTo(purchaseReq.getPrice()) == -1) {
            System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,审批终结!");
        } else {
            System.out.println("采购计划:"+purchaseReq.getPurpose()+",被"+this.name+"处理,进入下一级审批!");
            approver.process(purchaseReq);
        }
    }
}

测试类

package com.common.demo.pattern.chain;

import java.math.BigDecimal;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 测试类
 * @date 2023/07/27 14:23:01
 */
public class Test {

    public static void main(String[] args) {

        PurchaseReq purchaseRequest1 = new PurchaseReq(1, new BigDecimal(1000), "购买饮水机");
        PurchaseReq purchaseRequest2 = new PurchaseReq(2, new BigDecimal(6000), "购买打印机");
        PurchaseReq purchaseRequest3 = new PurchaseReq(2, new BigDecimal(30000), "购买苹果笔记本办公");

        ProjectManager projectManager = new ProjectManager("项目经理");
        DepartmentManager departmentManager = new DepartmentManager("部门经理");
        GeneralManager generalManager = new GeneralManager("总经理");
        //设置下一级处理人
        projectManager.setApprover(departmentManager);
        departmentManager.setApprover(generalManager);
        //都从项目经理开始处理
        projectManager.process(purchaseRequest1);
        projectManager.process(purchaseRequest2);
        projectManager.process(purchaseRequest3);

    }
}

测试截图

责任链模式的特点

优点

  1. 降低耦合度:将请求和处理分开,请求的发送者和接收者各个组件间完全解耦。
  2. 简化了对象:使得对象不需知道链的结构,请求者无需知道接受者,无需知道其如何处理。
  3. 增强灵活性:通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任对象。 
  4. 新增便捷性:增加新的请求处理类很方便。

缺点

  1. 因为只关心自己内部实现,不关心链内部结构,开发调试会比较麻烦。不容易确认调用的哪一个实现。
  2. 增加系统的资源消耗。因为链式调用,可能会进行很多次判断,因为每个实现都会判断是否能够处理该请求,不能处理则调用下一个,增加了系统开销。
  3. 不能保证请求被消化,因其特殊特性,在处理之前会判断是否能够处理,如果每一个链都不能处理,那么该请求无法被消化。

使用场景

  1. 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 
  3. 可动态指定一组对象处理请求。

注意事项

  1. 合理设计责任链的节点:责任链模式的核心是将任务分解为一系列的处理节点,每个节点都有机会处理任务或将其传递给下一个节点。在设计责任链节点时,需要根据实际情况合理地划分节点责任,确保每个节点的功能清晰、独立、可扩展,并且能够按需组合形成不同的责任链。
  2. 灵活配置责任链:责任链模式支持动态配置责任链,也就是可以在运行时通过添加、移除或修改节点来构建不同的责任链。这种灵活性可以根据实际需求动态调整责任链的结构和顺序,但也需要注意避免责任链过长、过于复杂,以及节点的重叠或缺失等问题。
  3. 节点的执行顺序:责任链模式中,每个节点都有机会处理任务,但处理的顺序是非常重要的。在设计责任链时,需要仔细考虑节点的执行顺序,确保任务能够按照预期的流程依次经过每个节点,同时避免出现死循环或执行顺序混乱等问题。
  4. 避免责任链的滥用:责任链模式可以很好地解耦请求发送者和接收者之间的关系,但也容易被滥用。在应用责任链模式时,需要审慎选择,确保责任链模式能够带来真正的价值,而不是增加复杂性或降低代码可维护性。
  5. 错误处理机制:在责任链模式中,如果没有合适的节点处理任务,任务可能会无法得到处理或处理结果不符合预期。因此,在设计责任链时,需要考虑错误处理机制,例如设置默认处理节点、定义异常处理策略等,以确保任务能够得到妥善处理,并且在发生异常时能够及时进行处理和反馈。

实际应用

  1. Spring框架中的拦截器:拦截器是Spring框架中的一种常见组件,它可以在请求处理前后进行一些额外的处理,例如身份验证、日志记录、权限控制等。拦截器就是利用了责任链模式来将多个处理对象构成一条拦截器链,然后逐个处理请求。Spring框架提供了很多拦截器,例如HandlerInterceptor、WebRequestInterceptor等。
  2. Servlet中的过滤器:Servlet中的过滤器也是一种常见的使用责任链模式的场景。过滤器可以在请求处理前后进行一些额外的处理,例如安全认证、数据预处理、异常处理等。
  3. Java 8中的Lambda表达式:Java 8中的Lambda表达式可以看作是一种函数式接口,它利用责任链模式来组合、封装和传递函数对象。Lambda表达式可以通过链式结构形成一个函数的序列,然后按顺序逐个执行这些函数并返回结果,从而可以在Java中实现函数式编程。
  4. Netty中的处理器Pipeline:Netty是一种基于事件驱动的网络通信框架,它利用责任链模式和事件监听机制来处理请求。Netty中的处理器Pipeline是一条处理请求的链,该链中的每个处理器都可以对请求进行处理和传递,从而形成一个完整的事件处理流程。

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值