责任链模式的应用与解析

news2024/9/22 13:44:55

目录

  • 责任链模式
    • 责任链模式结构
    • 责任链模式适用场景
    • 责任链模式优缺点
    • 练手题目
      • 题目描述
      • 输入描述
      • 输出描述
      • 题解

责任链模式

责任链模式,亦称职责链模式、命令链,是一种行为设计模式,允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

责任链模式结构

在这里插入图片描述

  1. 处理者(Handler)声明了所有具体处理者的通用接口。该接口通常仅包含单个方法用于请求处理,但有时其还会包含一个设置链上下个处理者的方法。

  2. 基础处理者(Base Handler)是一个可选的类,你可以将所有处理者共用的样本代码放置在其中。通常情况下,该类中定义了一个保存对于下个处理者引用的成员变量。 客户端可通过将处理者传递给上个处理者的构造函数或设定方法来创建链。该类还可以实现默认的处理行为:确定下个处理者存在后再将请求传递给它。

  3. 具体处理者(Concrete Handlers)包含处理请求的实际代码。每个处理者接收到请求后,都必须决定是否进行处理,以及是否沿着链传递请求。处理者通常是独立且不可变的,需要通过构造函数一次性地获得所有必要地数据。

  4. 客户端(Client)可根据程序逻辑一次性或者动态地生成链。值得注意的是,请求可发送给链上的任意一个处理者,而非必须是第一个处理者。

责任链模式通用代码:

//抽象处理者
public abstract class Handler{
    //下一个处理者
	private Handler nextHandler;
	// 对请求做出处理
	public final Response handleMessage(Request request){
		Response response = null ;
		//判断处理级别
		if(this.getHandlerLever().equals(request.getHandlerLever())){
			 response = this.echo(request);
	}else{
			 if(this.nextHandler != null){
				 response = this.nextHandler.handleMessage(request);
			 }else{
				 ...
			 }
			 return response;
	}
	
	public void setNext(Handler _handler){
		this.nextHandler = _handler;
	}
    
    //处理级别
    protected abstract Level getHandlerLevel();
    //处理任务
    protected abstract Response echo(Request request);

}

//具体处理者
public class ConcreteHandler1 extends Handler {
    //级别
    protected abstract Level getHandlerLevel(){
    ...
}
    //处理任务
    protected abstract Response echo(Request request){
    ...
}
}

public class Level{
    
}

public class Request{
    public Level getRequestLevel(){
        ...
    }
}

public class Response{
    ...
}

责任链模式适用场景

  1. 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。

  2. 当必须按顺序执行多个处理者时, 可以使用该模式。

  3. 如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式。

在这里插入图片描述

**识别方法:**该模式可通过一组对象的行为方法间接调用其他对象的相同方法来识别, 而且所有对象都会遵循相同的接口。

责任链模式优缺点

责任链模式优点:

  • 你可以控制请求处理的顺序。

  • 单一职责原则。 你可对发起操作和执行操作的类进行解耦。

  • 开闭原则。 你可以在不更改现有代码的情况下在程序中新增处理者。

责任链模式缺点:

  • 部分请求可能未被处理。

练手题目

题目描述

小明所在的公司请假需要在OA系统上发布申请,整个请求流程包括多个处理者,每个处理者负责处理不同范围的请假天数,如果一个处理者不能处理请求,就会将请求传递给下一个处理者,请你实现责任链模式,可以根据请求天数找到对应的处理者。

审批责任链由主管(Supervisor), 经理(Manager)和董事(Director)组成,他们分别能够处理3天、7天和10天的请假天数。如果超过10天,则进行否决。

输入描述

第一行是一个整数N(1 <= N <= 100), 表示请求申请的数量。

接下来的N行,每行包括一个请求申请的信息,格式为"姓名 请假天数"

输出描述

对于每个请假请求,输出一行,表示该请求是否被批准。如果被批准/否决,输出被哪一个职级的人批准/否决。

在这里插入图片描述

题解

初始解法:

import java.util.Scanner;

/**
 * 抽象处理器类,定义了责任链的基本结构
 */
abstract class Handler {
    public final static int SUPERVISOR_LEVEL_REQUEST = 1;
    public final static int MANAGER_LEVEL_REQUEST = 2;
    public final static int DIRECTOR_LEVEL_REQUEST = 3;
    
    private Handler nextHandler;
    private int level = 0;
    
    public Handler(int level) {
        this.level = level;
    }
    
    /**
     * 处理请求的方法
     * @param request 需要处理的请求
     * @return 处理结果
     */
    public final Response handleRequest(Request request) {
        if (this.level == request.getRequestLevel()) {
            return this.response(request);
        } else {
            if (this.nextHandler != null) {
                return this.nextHandler.handleRequest(request);
            } else {
                return new Response("Request denied");
            }
        }
    }
    
    /**
     * 设置下一个处理器
     * @param nextHandler 下一个处理器
     */
    public void setNext(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }
    
    /**
     * 具体的响应方法,由子类实现
     * @param request 需要处理的请求
     * @return 处理结果
     */
    protected abstract Response response(Request request);
}

/**
 * 主管处理
 */
class SupervisorHandler extends Handler {
    public SupervisorHandler() {
        super(Handler.SUPERVISOR_LEVEL_REQUEST);
    }
    
    @Override
    protected Response response(Request request) {
        System.out.println(request.getName() + " Approved by Supervisor.");
        return new Response("Approved by Supervisor");
    }
}

/**
 * 经理处理
 */
class ManagerHandler extends Handler {
    public ManagerHandler() {
        super(Handler.MANAGER_LEVEL_REQUEST);
    }
    
    @Override
    protected Response response(Request request) {
        System.out.println(request.getName() + " Approved by Manager.");
        return new Response("Approved by Manager");
    }
}

/**
 * 董事处理
 */
class DirectorHandler extends Handler {
    public DirectorHandler() {
        super(Handler.DIRECTOR_LEVEL_REQUEST);
    }
    
    @Override
    protected Response response(Request request) {
        System.out.println(request.getName() + " Approved by Director.");
        return new Response("Approved by Director");
    }
}

/**
 * 请求类,包含请求的详细信息
 */
class Request {
    private String name;
    private int level = 0;
    private int nums;
    
    public Request(String name, int nums) {
        this.name = name;
        this.nums = nums;
        if (nums > 0 && nums <= 3) {
            level = Handler.SUPERVISOR_LEVEL_REQUEST;
        } else if (nums > 3 && nums <= 5) {
            level = Handler.MANAGER_LEVEL_REQUEST;
        } else if (nums > 5 && nums <= 10) {
            level = Handler.DIRECTOR_LEVEL_REQUEST;
        } else {
            level = -1;
        }
    }
    
    public int getRequestLevel() { return this.level; }
    public String getName() { return this.name; }
    public int getNums() { return this.nums; }
}

/**
 * 响应类,包含处理结果
 */
class Response {
    private String message;
    
    public Response(String message) {
        this.message = message;
    }
    
    public String getMessage() {
        return this.message;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 创建处理器链
        SupervisorHandler supervisorHandler = new SupervisorHandler();
        ManagerHandler managerHandler = new ManagerHandler();
        DirectorHandler directorHandler = new DirectorHandler();
        
        supervisorHandler.setNext(managerHandler);
        managerHandler.setNext(directorHandler);
        
        int n = scanner.nextInt();
        scanner.nextLine(); 
        while (n-- > 0) {
            String[] s = scanner.nextLine().split(" ");
            Request request = new Request(s[0], Integer.parseInt(s[1]));
            Response response = supervisorHandler.handleRequest(request);
            if (request.getRequestLevel() == -1) {
                System.out.println(request.getName() + " Denied by Director.");
            }
        }
        
        scanner.close();
    }
}

优化后:

import java.util.Scanner;

// 抽象处理器类,定义了责任链的基本结构
abstract class Handler {
    public final static int SUPERVISOR_LEVEL_REQUEST = 1;
    public final static int MANAGER_LEVEL_REQUEST = 2;
    public final static int DIRECTOR_LEVEL_REQUEST = 3;
    
    private Handler nextHandler;
    private int level = 0;
    
    // 构造函数,设置处理器的级别
    public Handler(int _level) {
        this.level = _level;
    }
    
    // 处理请求的方法
    public final Response handleMessage(Request request) {
        if (this.level == request.getRequestLevel()) {
            return this.response(request);
        } else {
            if (this.nextHandler != null) {
                return this.nextHandler.handleMessage(request);
            } else {
                return new Response("Request denied");
            }
        }
    }
    
    // 设置下一个处理器
    public void setNext(Handler _handler) {
        this.nextHandler = _handler;
    }
    
    protected abstract Response response(Request request);
}

// 主管处理
class SupervisorHandler extends Handler {
    public SupervisorHandler() {
        super(Handler.SUPERVISOR_LEVEL_REQUEST);
    }
    
    @Override
    protected Response response(Request request) {
        System.out.println(request.getName() + " Approved by Supervisor.");
        return new Response("Approved by Supervisor");
    }
}

// 经理处理
class ManagerHandler extends Handler {
    public ManagerHandler() {
        super(Handler.MANAGER_LEVEL_REQUEST);
    }
    
    @Override
    protected Response response(Request request) {
        System.out.println(request.getName() + " Approved by Manager.");
        return new Response("Approved by Manager");
    }
}

// 董事处理
class DirectorHandler extends Handler {
    public DirectorHandler() {
        super(Handler.DIRECTOR_LEVEL_REQUEST);
    }
    
    @Override
    protected Response response(Request request) {
        System.out.println(request.getName() + " Approved by Director.");
        return new Response("Approved by Director");
    }
}

// 请求级别的枚举,定义了不同级别的请假天数范围
enum RequestLevel {
    SUPERVISOR(1, 3),
    MANAGER(4, 5),
    DIRECTOR(6, 10);

    private final int minDays;
    private final int maxDays;

    RequestLevel(int minDays, int maxDays) {
        this.minDays = minDays;
        this.maxDays = maxDays;
    }

    // 根据天数确定请求级别
    public static RequestLevel fromDays(int days) {
        for (RequestLevel level : values()) {
            if (days >= level.minDays && days <= level.maxDays) {
                return level;
            }
        }
        return null;
    }

    public int getValue() {
        return ordinal() + 1;
    }
}

// 请求类,包含请求的详细信息
class Request {
    private String name;
    private int level;
    private int nums;
    
    public Request(String name, int nums) {
        this.name = name;
        this.nums = nums;
        RequestLevel requestLevel = RequestLevel.fromDays(nums);
        this.level = (requestLevel != null) ? requestLevel.getValue() : -1;
    }
    
    public int getRequestLevel() {
        return this.level;
    }
    
    public String getName() {
        return this.name;
    }
    
    public int getNums() {
        return this.nums;
    }
}

// 响应类,包含处理结果
class Response {
    private String message;
    
    public Response(String message) {
        this.message = message;
    }
    
    public String getMessage() {
        return this.message;
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 创建处理器链
        SupervisorHandler supervisorHandler = new SupervisorHandler();
        ManagerHandler managerHandler = new ManagerHandler();
        DirectorHandler directorHandler = new DirectorHandler();
        
        // 设置处理器链的顺序
        supervisorHandler.setNext(managerHandler);
        managerHandler.setNext(directorHandler);
        
        int n = scanner.nextInt();
        scanner.nextLine(); 
        
        // 处理每个请求
        while (n-- > 0) {
            String[] s = scanner.nextLine().split(" ");
            Request request = new Request(s[0], Integer.parseInt(s[1]));
            Response response = supervisorHandler.handleMessage(request);
            if (request.getRequestLevel() == -1) {
                System.out.println(request.getName() + " Denied by Director.");
            }
        }
        
        scanner.close();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1944863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

韩顺平0基础学java——第36天

p715-735 反射调用速度慢 反射调用优化-关闭访问检查 1. Method和Field、Constructor对象都有setAccessible() 方法2. setAccessible作用是启动和禁用访问安全检查的开关 3&#xff0e;参数值为true表示反射的对象在使用时取消访问检查&#xff0c;提高反射的效率。参数值 为…

Redis核心技术与实战学习笔记

Redis核心技术与实战学习笔记 最近想沉下心来看下redis&#xff0c;买了蒋德钧老师的《Redis 核心技术与实战》,这里记录一些学习笔记 希望能够坚持下去有想一起学习的童鞋&#xff0c;可以点击跳转到文章尾部获取学习资源,仅供学习不要用于任何商业用途!!! redis知识全景图 …

2024-07-22 Unity AI行为树1 —— 框架介绍

文章目录 1 行为树2 行为树驱动方式3 行为树结点分类3.1 控制节点3.2 执行节点 4 行为树与状态机比较 本文章参考 B 站唐老狮 2023年直播内容。 点击前往唐老狮 B 站主页。 1 行为树 ​ 行为树&#xff08;Behavior Tree&#xff0c;BT&#xff09;在游戏 AI 中是一种用于控制…

精益管理意识与企业战略规划的匹配度如何评估?

众所周知&#xff0c;精益管理不仅要求企业在生产运营过程中实现资源的最大化利用&#xff0c;同时也强调企业战略规划的精准性和前瞻性。因此&#xff0c;评估精益管理意识与企业战略规划的匹配度&#xff0c;对于企业的长期发展至关重要。具体方法如深圳天行健企业管理咨询公…

springboot 项目整合 AI (文心一言)

百度智能云网址&#xff1a;https://cloud.baidu.com/?fromconsole 注册——个人认证——登录成功 第一步&#xff1a;点击千帆大模型平台 ​ 第二步&#xff1a;点击应用接入——创建应用 ​ 第三步&#xff1a;点击接口文档——API列表——可以点击指定模型进行查看调…

【中项】系统集成项目管理工程师-第4章 信息系统架构-4.4数据架构

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

hamcrest 断言框架使用示例和优势分析

引言 在软件测试领域&#xff0c;断言是验证代码行为是否符合预期的关键环节。Hamcrest 断言框架&#xff0c;以其独特的匹配器&#xff08;Matcher&#xff09;概念和清晰的失败信息&#xff0c;赢得了广泛的赞誉。尽管 Python 标准库中没有内置的 Hamcrest 库&#xff0c;但…

【前端新手小白】学习Javascript的【开源好项目】推荐

目录 前言 1 项目介绍 1.1 时间日期类 1.2 网页store类 1.3 事件类 1.4 Number类 1.5 String类 1.6 正则验证类 1.7 ajax类 1.8 data数据类 1.9 browser浏览器类 2 学习js-tool-big-box开源项目时有哪些收获 2.1 你可以这样做 2.2 如果你需要使用本项目 2.3 你…

开局一个启动器:从零开始入坑ComfyUI

前几天刷某乎的时候看到了一位大佬写的好文&#xff0c;可图 IP-Adapter 模型已开源&#xff0c;更多玩法&#xff0c;更强生态&#xff01; - 知乎 (zhihu.com) 久闻ComfyUI大名&#xff0c;决定试一下。这次打算不走寻常路&#xff0c;不下载现成的一键包了&#xff0c;而是…

矩估计与最大似然估计的通俗理解

点估计与区间估计 矩估计与最大似然估计都属于点估计&#xff0c;也就是估计出来的结果是一个具体的值。对比区间估计&#xff0c;通过样本得出的估计值是一个范围区间。例如估计一个人的年龄&#xff0c;点估计就是最终直接估计年龄为50岁&#xff0c;而区间估计是最终估计的…

Qt源码交叉编译带openssl的Qt版本

一.背景 近期项目由于对接的后台服务是https的&#xff0c;之前交叉编译的Qt是不带openssl的&#xff0c;为了能支持https&#xff0c;必须要重新编译Qt。 二.环境 环境准备&#xff1a; Ubuntu版本 &#xff1a;18.04&#xff1b; openssl 版本&#xff1a;1.1.1.g&#xff1b…

go-kratos 学习笔记(5) 删除hellword从新生成服务

go-kratos 删除hellword模版里的服务&#xff0c;从新生成服务users 直接删除api/helloword 目录&#xff0c;在api目录下新建 users目录&#xff1b;使用命令生成新的proto #项目根目录执行 kratos proto add api/users/user.protobuf generate生成的user.proto需要根据自己…

CCS光源的高输出TH2系列平面光源

光源在机器视觉系统中起着重要作用&#xff0c;不同环境、场景及应用合适光源都不一样&#xff0c;今天我们来看看高输出TH2系列平面光源。它可以对应高速化的生产线&#xff0c;为提高生产效率做出贡献。 TH2系列光源的特点&#xff1a; 1、实现了更高一级的高亮度 实现了更…

Ubuntu22.04系统安装nodejs 14 保姆级教程

下载软件包 从NodeSource 的官方源下载并安装 Node.js 14.x 版本的软件包&#xff0c;适用于 Debian 和 Ubuntu 系统&#xff1a; curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - 更新软件源 更新软件源 sudo apt-get update 下载bodejs14 下载nodejs14 sud…

Doris全方位教程+应用实例

Impala性能稍领先于presto,但是presto在数据源支持上非常丰富&#xff0c;包括hive、图数据库、传统关系型数据库、Redis等 缺点&#xff1a;这两种对hbase支持的都不好&#xff0c;presto 不支持&#xff0c;但是对hdfs、hive兼容性很好&#xff0c;其实这也是顺理成章的&…

单片机学习(18)--红外遥控器

红外遥控器 17.1红外遥控的基础知识1.红外遥控简介2.硬件电路3.基本发送和接收4.NEC编码5.遥控器键码6.51单片机的外部中断7.外部中断寄存器 17.2红外遥控的程序代码1.红外遥控&#xff08;1&#xff09;工程目录&#xff08;2&#xff09;main.c函数&#xff08;3&#xff09;…

ubuntu在命令行输出里查找内容,dmesg

直接执行查看日志指令会出来很多页。dmesg为开机日志信息。记录了开机时硬件的过程 sudo dmesg 执行结果&#xff1a; 可以用竖号“|”&#xff0c;在前一条命令返回的内容进行查找。下图为查找bluetooth sudo dmesg |grep -i bluetooth

ufw命令简介

正文共&#xff1a;3999 字 41 图&#xff0c;预估阅读时间&#xff1a;4 分钟 我们之前在CentOS系统中研究了iptables命令的使用方法&#xff08;iptables命令简介&#xff09;&#xff0c;还做了简单的应用实验&#xff08;如何通过iptables配置URL过滤黑名单&#xff1f;、如…

DevExpress WinForms自动表单布局,创建高度可定制用户体验(二)

使用DevExpress WinForms的表单布局组件可以创建高度可定制的应用程序用户体验&#xff0c;从自动安排UI控件到按比例调整大小&#xff0c;DevExpress布局和数据布局控件都可以让您消除与基于像素表单设计相关的麻烦。 P.S&#xff1a;DevExpress WinForms拥有180组件和UI库&a…

LeetCode:删除排序链表中的重复元素(C语言)

1、问题概述&#xff1a;给定一个已排序链表的头&#xff0c;删除重复元素&#xff0c;返回已排序的链表 2、示例 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输出&#xff1a;[1,2,3] 3…