设计模式 - 行为型考点模式:责任链模式(概述 | 案例实现 | 优缺点 | 使用场景)

news/2024/5/19 16:03:23 标签: 设计模式, 责任链模式

目录

一、行为型模式

1.1、责任链模式

1.1.1、概述

1.1.2、案例实现

1.1.3、优缺点

1.1.4、使用场景


一、行为型模式


1.1、责任链模式

1.1.1、概述

为了避免请求发送者和多个请求处理者耦合在一起,就将所有请求处理者通过前一个对象记住下一个对象的引用的方式形成一条链;当有请求到来时,可以将请求沿着这条链传递,知道有对象能处理他为止.

例如,公司员工请假,可以批假的领导有小组组长、部门经理、总经理,但是每个领导比准的天数不同,那么员工请假时,就需要记住每一个领导的能请假的天数,十分不方便,但是通过责任链模式,你就可以直接把假条先交给能处理天数最少的人即可,如果小组组长处理不了,小组组长因为持有 部门经理 的引用,就可以找到他,让他处理..... 以此类推,直到找到能处理这个假条的领导为止.

责任链模式主要包含以下角色:

  • 抽象处理者:定义一个处理请求的接口,包含抽象处理方法并持有下一个处理者的引用.
  • 具体处理者:实现抽象处理者的处理方法,判断当前处理者能否处理请求,如果可以就处理,不可以就交给下一个处理者处理.(例如上述的,小组组长、部门经理、总经理)
  • 客户类:创建处理链,并向链头的具体处理者对象提交请求,他不关心具体的处理细节和请求的传递过程.

1.1.2、案例实现

实现上述案例.

/**
 * 请假条类
 */
public class LeaveRequest {

    //请假人姓名
    private String name;
    //请假天数
    private int num;
    //请假原因
    private String reason;

    public LeaveRequest(String name, int num, String reason) {
        this.name = name;
        this.num = num;
        this.reason = reason;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }
    
}
/**
 * 抽象处理者
 */
public abstract class Handler {

    //请假天数
    protected static final int ONE_DAY = 1;
    protected static final int THREE_DAY = 3;
    protected static final int SEVEN_DAY = 7;

    //各级领导能处理请假天数区间
    private int numStart;
    private int numEnd;

    //领导的领导
    private Handler nextHandler;

    /**
     * 领导处理请假天数区间
     * @param numStart
     * @param numEnd
     */
    public Handler(int numStart, int numEnd) {
        this.numStart = numStart;
        this.numEnd = numEnd;
    }

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 提交请假请求
     */
    public final void submit(LeaveRequest request) {
        if(request.getNum() <= numEnd) {
            this.handlerLeave(request);
        } else if(this.nextHandler != null) {
            nextHandler.submit(request);
        } else {
            System.out.println("请假天数超过上限!");
        }
    }

    protected abstract void handlerLeave(LeaveRequest request);

}
/**
 * 具体处理者: 小组组长
 */
public class GroupLeader extends Handler {

    /**
     * 小组长所能处理的请假天数区间
     */
    public GroupLeader() {
        super(0, ONE_DAY);
    }

    @Override
    protected void handlerLeave(LeaveRequest request) {
        System.out.println(request.getName() + "请假 " + request.getNum() + " 天," +
                request.getReason());
        System.out.println("小组长审批通过");
    }

}
/**
 * 具体处理者: 部门经理
 */
public class Manager extends Handler {

    /**
     * 经理所能处理的请假天数区间
     */
    public Manager() {
        super(ONE_DAY, THREE_DAY);
    }

    @Override
    protected void handlerLeave(LeaveRequest request) {
        System.out.println(request.getName() + "请假 " + request.getNum() + " 天," +
                request.getReason());
        System.out.println("部门经理审批通过");
    }

}
/**
 * 具体处理者: 总经理
 */
public class GeneralManager extends Handler {

    /**
     * 经理所能处理的请假天数区间
     */
    public GeneralManager() {
        super(THREE_DAY, SEVEN_DAY);
    }

    @Override
    protected void handlerLeave(LeaveRequest request) {
        System.out.println(request.getName() + "请假 " + request.getNum() + " 天," +
                request.getReason());
        System.out.println("总经理审批通过");
    }

}
/**
 * 客户类
 */
public class Client {

    public static void main(String[] args) {
        //1.假条
        LeaveRequest request1 = new LeaveRequest("李白", 1, "这几天要出诗集~");
        LeaveRequest request2 = new LeaveRequest("杜甫", 3, "生病了,身体不适~");
        LeaveRequest request3 = new LeaveRequest("龙洋静", 6, "着急结婚!");

        //2.责任链关系
        GroupLeader groupLeader = new GroupLeader();
        Manager manager = new Manager();
        GeneralManager generalManager = new GeneralManager();

        groupLeader.setNextHandler(manager);
        manager.setNextHandler(generalManager);

        //3.提交假条
        groupLeader.submit(request1);
        System.out.println("===============");
        groupLeader.submit(request2);
        System.out.println("===============");
        groupLeader.submit(request3);
    }

}

执行结果如下:

1.1.3、优缺点

优点:

  1. 解耦合:降低了发送请求者和处理请求者的耦合度.
  2. 满足开闭原则:可以根据业务需求,新增请求处理类.
  3. 增强了对象指派责任的灵活性:当工作流程发生变化,可以动态的改变链内成员或者修改他们的次序,也可以动态的新增和删除责任.
  4. 简化了对象链接:一个对象只需要持有下一个后继者的引用,不需要保持其他所有处理者的引用,避免了众多的 if else 语句.
  5. 满足单一职责:每个类只需要处理自己的工作,不能处理就交给下一个对象完成.

缺点:

不能保证每一个请求一定被处理:因为请求没有明确的接收者,因此不能保证他一定被处理,该请求可能传到链末也得不到处理.

性能影响:如果责任链较长,请求的处理可能涉及到多个对象,性能会有所损耗.

复杂度:责任链的合理性全靠客户端来保证,增加了客户端的复杂度.

1.1.4、使用场景

1. 多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定.

2. 请求者不明确要对哪一个对象进行提交申请.

例如像公司职级审批流的设定.

例如用户找回密码需要一步步校验的密保信息.


http://www.niftyadmin.cn/n/5079848.html

相关文章

17.(开发工具篇Gitlab)如何在Gitlab配置ssh key

前言: Git是分布式的代码管理工具,远程的代码管理是基于SSH的,所以要使用远程的Git则需要SSH的配置 一、git 配置 (1)打开 git 命令窗口 (2)配置用户名(填自己的姓名) git config --global user.name “chenbc” (3)配置用户邮箱(填自己的邮箱) git config …

干货:如何在前端统计用户访问来源?

在前端统计用户访问来源是一个常见的需求&#xff0c;通过获取访问来源信息&#xff0c;我们可以了解用户是通过直接访问、搜索引擎、外部链接等途径进入我们的网站或应用。下面是一个详细的介绍&#xff0c;包括方法和实现步骤。 一、获取HTTP Referer HTTP Referer是HTTP请…

STM32单片机入门学习(六)-光敏传感器控制LED

光敏传感器模块和LED接线 LED负极接B12,正极接VCC 光敏传感模块一DO端接B13,GND接GND&#xff0c;VCC接VCC,AO不接。 如图&#xff1a; 主程序代码&#xff1a;main.c #include "stm32f10x.h" #include "Delay.h" //delay函数所在头文件 #include …

Ubuntu查看自身版本,系统架构

打开终端。 在终端中输入以下命令并按Enter键&#xff1a; lsb_release -awubwub:/$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.3 LTS Release: 22.04 Codename: jammy确定linux版本 cat /etc/lsb-release DISTRIB_IDU…

服务器编程基本框架

服务器编程基本框架 虽然服务器程序种类繁多&#xff0c;但其基本框架都一样&#xff0c;不同之处在于逻辑处理。 I/O 处理单元是服务器管理客户连接的模块。它通常要完成以下工作&#xff1a;等待并接受新的客户连接&#xff0c;接收客户数据&#xff0c;将服务器响应数据返回…

HTML5的新增表单元素

HTML5 有以下新的表单元素: <datalist> <keygen> <output> datalist datalist 元素规定输入域的选项列表。 datalist属性规定 form 或 input 域应该拥有自动完成功能。当用户在自动完成域中开始输入时&#xff0c;浏览器应该在该域中显示填写的选项&…

使用 Databend Kafka Connect 构建实时数据同步

作者&#xff1a;韩山杰 Databend Cloud 研发工程师 hantmac (Jeremy) GitHub Kafka Connect 介绍 Kafka Connect 是一个用于在 Apache Kafka 和其他数据系统之间可扩展且可靠地流式传输数据的工具。通过将数据移入和移出 Kafka 进行标准化&#xff0c;使得快速定义连接器以在…

Vue中的router路由的介绍(快速入门)

路由的介绍 文章目录 路由的介绍1、VueRouter的介绍2、VueRouter的使用&#xff08;52&#xff09;2.1、5个基础步骤(固定)2.2、两个核心步骤 3、组件存放的目录&#xff08;组件分类&#xff09; 生活中的路由&#xff1a;设备和ip的映射关系&#xff08;路由器&#xff09; V…